diff --git a/.github/workflows/RELEASE.HEAD.md b/.github/workflows/RELEASE.HEAD.md index 09d3a13bd6aa2..7c3d9e2be5263 100644 --- a/.github/workflows/RELEASE.HEAD.md +++ b/.github/workflows/RELEASE.HEAD.md @@ -2,6 +2,6 @@ #### How to Install the Developer Build: -- **Firefox**: Signing pending - uBO works best on Gecko-based browsers, check out [why](https://github.com/gorhill/uBlock/wiki/uBlock-Origin-works-best-on-Firefox). -- **Chromium**: Install directly from the [Chrome Web Store](https://chromewebstore.google.com/detail/ublock-origin-development/cgbcahbpdhpcegmbfconppldiemgcoii). +- **Firefox**: Download the build from [uBlock0_%version%.firefox.signed.xpi](https://github.com/gorhill/uBlock/releases/download/%version%/uBlock0_%version%.firefox.signed.xpi) + uBO works best on Gecko-based browsers, check out [why](https://github.com/gorhill/uBlock/wiki/uBlock-Origin-works-best-on-Firefox) +- **Chromium**: Install directly from [signed CRX package](https://github.com/gorhill/uBlock/releases/download/%version%/uBlock0_%version%.chromium.crx) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index eeb9c77cf5861..b2cc2755fa005 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -36,15 +36,14 @@ jobs: sed -e 's/%version%/${{ env.VERSION }}/g' .github/workflows/RELEASE.HEAD.md >> release.body.txt - name: Create GitHub release id: create_release - uses: softprops/action-gh-release@v2 env: - GITHUB_TOKEN: ${{ github.token }} - with: - tag_name: ${{ env.VERSION }} - name: ${{ env.VERSION }} - draft: true - prerelease: true - body_path: release.body.txt - files: | - dist/build/uBlock0_${{ env.VERSION }}.chromium.zip + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create ${{ env.VERSION }} \ + --title "${{ env.VERSION }}" \ + --prerelease \ + --draft \ + --notes-file release.body.txt + gh release upload ${{ env.VERSION }} \ + dist/build/uBlock0_${{ env.VERSION }}.chromium.zip \ dist/build/uBlock0_${{ env.VERSION }}.firefox.xpi diff --git a/.gitmodules b/.gitmodules index dc2159e539902..e750b4e566109 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "publish-extension"] path = publish-extension url = https://github.com/gorhill/publish-extension.git +[submodule "platform/mv3/extension/lib/s14e-serializer"] + path = platform/mv3/extension/lib/s14e-serializer + url = https://github.com/gorhill/s14e-serializer.git diff --git a/CHANGELOG.md b/CHANGELOG.md index 84018c07ceb98..a2847a9609077 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,77 @@ +- [Improve `remove-attr` scriptlet](https://github.com/gorhill/uBlock/commit/bd98bcace0) +- [Fix parsing of invalid regex-like domain in static extended filters](https://github.com/gorhill/uBlock/commit/bfbd7f609e) +- [Improve `remove-node-text`/`replace-node-text` scriptlets](https://github.com/gorhill/uBlock/commit/71faa0b23f) +- [Improve `prevent-clipboard-write` scriptlet](https://github.com/gorhill/uBlock/commit/457c510093) +- [Address multiple static filter parser issues](https://github.com/gorhill/uBlock/commit/3ab731942e) +- [Treat resources with data as redirectable](https://github.com/gorhill/uBlock/commit/c9eb5b276d) +- [Add `mpegdash-prune` scriptlet](https://github.com/gorhill/uBlock/commit/323b4ce279) +- [Improve `xmlPrune` scriptlet](https://github.com/gorhill/uBlock/commit/1235e4dd27) +- [Improve procedural operator `:matches-path()`](https://github.com/gorhill/uBlock/commit/43d3c74ce7) + +---------- + +# 1.74.0 + +- [Fix possible injection of scriptlets requiring trust from non-trusted sources](https://github.com/gorhill/uBlock/commit/a46d5c8e75) +- [Import `google-ima-dai` shim from AdGuard shims](https://github.com/gorhill/uBlock/commit/933efff4dd) +- [Replace List-KR with filterslists-KO](https://github.com/gorhill/uBlock/commit/20d3c5b9d0) +- [Remove support for `cap_user_stylesheet`](https://github.com/gorhill/uBlock/commit/fb09b0947d) +- [Improve scriptlets framework](https://github.com/gorhill/uBlock/commit/57ade5f484) +- [Add `env_brave` preparser token](https://github.com/gorhill/uBlock/commit/0c56103a40) (by @ryanbr) +- [Add set/unset/given cookie values](https://github.com/gorhill/uBlock/commit/a796fd7daf) (by @ryanbr) +- [Add procedural operator `content(...)`, to lookup elements inside `template` tags](https://github.com/gorhill/uBlock/commit/25d413803d) +- [Improve `prevent-clipboard-write` scriptlet](https://github.com/gorhill/uBlock/commit/8a85e04907) +- [Improve `json-edit` scriptlet](https://github.com/gorhill/uBlock/commit/0fdbfdb2b5) +- [Revisit scriptlets' `getExtraArgs` implementation](https://github.com/gorhill/uBlock/commit/505fbc7a75) + +---------- + +# 1.73.0 + +- [[logger] Preserve whitespace characters](https://github.com/gorhill/uBlock/commit/ef981d09b5) +- [Improve `proxy-apply` utility scriptlet](https://github.com/gorhill/uBlock/commit/be3bb05fce) +- [Improve `abort-current-script` scriptlet](https://github.com/gorhill/uBlock/commit/84e4bd7659) +- [Improve `prevent-addEventListener` scriptlet](https://github.com/gorhill/uBlock/commit/89fe40d73f) +- [Add shim for `piano-analytics.js`](https://github.com/gorhill/uBlock/commit/5dab3cbd24) +- [Improve `trusted-click-element` scriptlet](https://github.com/gorhill/uBlock/commit/bdd39fe606) +- [Add `prevent-clipboard-write` scriptlet](https://github.com/gorhill/uBlock/commit/735f61b8a4) +- [Improve `prevent-bab` scriptlet](https://github.com/gorhill/uBlock/commit/6772215c35) +- [[jsonpath] Increase RFC9535 compliance](https://github.com/gorhill/uBlock/commit/b123c23a4f) +- [Dot notation before bracket notation is not valid](https://github.com/gorhill/uBlock/commit/028ffdbea3) + +---------- + +# 1.72.2 + +- [Add missing test against `null` object](https://github.com/gorhill/uBlock/commit/74e6c8fe3f) + +---------- + +# 1.72.0 + +- [Fix broken rendering of final URL in strict-block page](https://github.com/gorhill/uBlock/commit/fe8ce9804c) +- [Fix potential exception in set-attribute scriptlet](https://github.com/gorhill/uBlock/commit/37fe5d9cbe) +- [Improve parsing/interpretation of consecutive `$$` in network filters](https://github.com/gorhill/uBlock/commit/347f9f7fda) +- [Improve `googlesyndication_adsbygoogle` shim](https://github.com/gorhill/uBlock/commit/f5be2bbed0) +- [Add `edit-object-on-[getter|setter]` scriptlets](https://github.com/gorhill/uBlock/commit/99e622831b) +- [JSONPath: Test presence/absence of property w/ quantifier extension](https://github.com/gorhill/uBlock/commit/b901692d57) +- [Prefix JSONPath queries with `v2:` to benefit increased rfc9535 conformance](https://github.com/gorhill/uBlock/commit/5d9ac5d0bf) +- [Add regex-based selectors to JSONPath](https://github.com/gorhill/uBlock/commit/cfc3b05c93) +- [Improve JSONPath; add `[trusted-]edit-element-object` scriptlets](https://github.com/gorhill/uBlock/commit/fdc1a4e743) +- [Improve JSONPath: add support for double quote for names](https://github.com/gorhill/uBlock/commit/fe45329032) +- [Add `edit-this-object`/`trusted-edit-this-object` scriptlets](https://github.com/gorhill/uBlock/commit/2695b9f7d6) +- [Minor improvement to `trusted-replace-argument` scriptlet](https://github.com/gorhill/uBlock/commit/da9287257d) +- [Fix test for header matching when using negated value](https://github.com/gorhill/uBlock/commit/09e46b744e) +- [Improve `trusted-click-element` scriptlet](https://github.com/gorhill/uBlock/commit/32a4d640fb) + - +- [Improve `google-ima` shim](https://github.com/gorhill/uBlock/commit/9e5299e7f4) +- [Add ISO-8859-2 as alias of Windows-1250 in text encoder](https://github.com/gorhill/uBlock/commit/3f0c4e1110) + +---------- + +# 1.71.0 + +- [Improve `freeze-element-property` scriptlet](https://github.com/gorhill/uBlock/commit/b91798c6f4) - [Add support for network filter option `top=`](https://github.com/gorhill/uBlock/commit/aebc108e36) - [Fix JS code extraction from web accessible resources](https://github.com/gorhill/uBlock/commit/a8bbd1a466) - [Add `freeze-element-property` scriptlet](https://github.com/gorhill/uBlock/commit/05f01f6be4) diff --git a/Makefile b/Makefile index 932ecf5613fa8..e3e30d4bf3cb4 100644 --- a/Makefile +++ b/Makefile @@ -105,8 +105,9 @@ publish-chromium: ghowner=gorhill \ ghrepo=uBlock \ ghtag=$(version) \ - ghasset=chromium \ - storeid=cjpalhdlnbpafiamejdnhcphjbkeiagm + ghasset=chromium.zip \ + crxupdatepath=dist/chromium/update.xml \ + crxkeytoken=ubo_dev_key_path # Usage: make publish-edge version=? publish-edge: @@ -114,7 +115,7 @@ publish-edge: ghowner=gorhill \ ghrepo=uBlock \ ghtag=$(version) \ - ghasset=chromium \ + ghasset=chromium.zip \ datebasedmajor=1 \ storeid=odfafepnkmbhccpbejgmiehpchacaeak \ productid=$(shell secret-tool lookup token ubo_edge_id) \ @@ -136,8 +137,9 @@ publish-dev-chromium: ghowner=gorhill \ ghrepo=uBlock \ ghtag=$(version) \ - ghasset=chromium \ - storeid=cgbcahbpdhpcegmbfconppldiemgcoii + ghasset=chromium.zip \ + crxupdatepath=dist/chromium/update-dev.xml \ + crxkeytoken=ubo_dev_key_path # Usage: make publish-dev-firefox version=? publish-dev-firefox: diff --git a/README.md b/README.md index 692a8482fee33..236e623ed5ce4 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Badge License]][License] [![Badge NPM]][NPM] [![Badge Mozilla]][Mozilla] -[![Badge Chrome]][Chrome] +![Badge Chrome] [![Badge Edge]][Edge] *** @@ -19,12 +19,20 @@ uBlock Origin (uBO) | Browser | Install from ... | Status | | :-------: | ---------------- | ------ | | Get uBlock Origin for Firefox | Firefox Add-ons | [uBO works best on Firefox](https://github.com/gorhill/uBlock/wiki/uBlock-Origin-works-best-on-Firefox) | -| Get uBlock Origin for Microsoft Edge | Edge Add-ons | +| Get uBlock Origin for Microsoft Edge | Edge Add-ons | "Moving the Microsoft Edge extensions ecosystem forward with Manifest Version 3": "Beginning in August 2026, Microsoft Edge will start the consumer transition away from Manifest Version 2 (MV2) extensions and toward MV3. Our goal is to complete the consumer transition by the end of 2026, with enterprise deprecation following in early 2027." | | Get uBlock Origin for Opera | Opera Add-ons | -| Get uBlock Origin for Chromium | Chrome Web Store | About Google Chrome's "This extension may soon no longer be supported"
End of support on Chrome 139 | +| Get uBlock Origin for Chromium | Removed | "Manifest V2 support timeline": "Aug 31st 2026: All remaining Manifest V2 extensions removed from the Chrome Web Store"
About Google Chrome's "This extension may soon no longer be supported" | | Get uBlock Origin for Thunderbird | Thunderbird Add-ons | [No longer updated and stuck at 1.49.2.](https://github.com/uBlockOrigin/uBlock-issues/issues/2928) Later versions require "GitHub - Releases". | | Get uBlock Origin through GitHub | GitHub - Releases | Stable and development versions on Firefox, Chromium MV2, and Thunderbird. Must be placed manually into web browsers; the Chromium and Thunderbird versions usually won't auto-update. +

Related: + + + +uBlock Origin Lite +

+ + *** uBlock Origin (uBO) is a CPU and memory-efficient [wide-spectrum content blocker][Blocking] for Chromium and Firefox. It blocks ads, trackers, coin miners, popups, annoying anti-blockers, malware sites, etc., by default using [EasyList][EasyList], [EasyPrivacy][EasyPrivacy], [Peter Lowe's Blocklist][Peter Lowe's Blocklist], [Online Malicious URL Blocklist][Malicious Blocklist], and uBO [filter lists][uBO Filters]. There are many other lists available to block even more. Hosts files are also supported. uBO uses the EasyList filter syntax and [extends][Extended Syntax] the syntax to work with custom rules and filters. @@ -40,8 +48,8 @@ Ads, "unintrusive" or not, are just the visible portion of the privacy-invading * [Documentation](#documentation) * [Installation](#installation) * [Firefox](#firefox) - * [Thunderbird](#thunderbird) * [Chromium](#chromium) + * [Thunderbird](#thunderbird) * [All Programs](#all-programs) * [Enterprise Deployment](#enterprise-deployment) * [Release History](#release-history) @@ -85,24 +93,22 @@ For support, questions, or help, visit [/r/uBlockOrigin][Reddit]. uBO [works best][Works Best] on Firefox and is available for desktop and Android versions. -#### Thunderbird - -[Thunderbird Add-ons][Thunderbird] - -In Thunderbird, uBlock Origin does not affect emails, just feeds. - #### Chromium -[Chrome Web Store][Chrome] +Chrome Web Store: Removed on 2026-08-31 [Microsoft Edge Add-ons][Edge] (Published by [Nicole Rolls][Nicole Rolls] until version 1.62. Ownership transfer at version 1.64.) [Opera Add-ons][Opera] -[Development Builds][Chrome Dev] - uBO should be compatible with any Chromium-based browser. +#### Thunderbird + +[Thunderbird Add-ons][Thunderbird] + +In Thunderbird, uBlock Origin does not affect emails, just feeds. + #### All Programs Do **NOT** use uBO with any other content blocker. uBO [performs][Performance] as well as or better than most popular blockers. Other blockers can prevent uBO's privacy or anti-blocker-defusing features from working correctly. @@ -141,11 +147,9 @@ If you ever want to contribute something, think about the people working hard to [Performance]: https://www.debugbear.com/blog/chrome-extensions-website-performance#the-impact-of-ad-blocking-on-website-performance [EasyPrivacy]: https://easylist.to/#easyprivacy [Thunderbird]: https://addons.thunderbird.net/thunderbird/addon/ublock-origin/ -[Chrome Dev]: https://chromewebstore.google.com/detail/ublock-origin-development/cgbcahbpdhpcegmbfconppldiemgcoii [EasyList]: https://easylist.to/#easylist [Mozilla]: https://addons.mozilla.org/addon/ublock-origin/ [Crowdin]: https://crowdin.com/project/ublock -[Chrome]: https://chromewebstore.google.com/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm [Reddit]: https://www.reddit.com/r/uBlockOrigin/ [Theft]: https://x.com/LeaVerou/status/518154828166725632 [Opera]: https://addons.opera.com/extensions/details/ublock/ diff --git a/assets/assets.dev.json b/assets/assets.dev.json index f015a6b599bf6..c0d6a960536c0 100644 --- a/assets/assets.dev.json +++ b/assets/assets.dev.json @@ -634,7 +634,7 @@ "content": "filters", "group": "regions", "off": true, - "title": "🇫🇷fr 🇨🇦ca: AdGuard Français", + "title": "🇫🇷fr 🇧🇪be 🇨🇦ca: AdGuard Français", "tags": "ads french", "lang": "ar br ff fr kab lb oc son", "contentURL": "https://filters.adtidy.org/extension/ublock/filters/16.txt", @@ -754,11 +754,11 @@ "content": "filters", "group": "regions", "off": true, - "title": "🇰🇷kr: List-KR Classic", + "title": "🇰🇷kr: 한국어 (Korean)", "tags": "ads korean 한국어", "lang": "ko", - "contentURL": "https://cdn.jsdelivr.net/npm/@list-kr/filterslists@latest/dist/filterslist-uBlockOrigin-classic.txt", - "supportURL": "https://github.com/List-KR/List-KR#readme" + "contentURL": "https://cdn.jsdelivr.net/npm/@filteringdev/filterslists-ko@latest/dist/filterslist-uBlockOrigin-classic.txt", + "supportURL": "https://github.com/FilteringDev/filterslists-KO#filteringdevfilterslists-ko" }, "LTU-0": { "content": "filters", diff --git a/assets/assets.json b/assets/assets.json index 62e5fd33b2d62..bc9f004f5da04 100644 --- a/assets/assets.json +++ b/assets/assets.json @@ -634,7 +634,7 @@ "content": "filters", "group": "regions", "off": true, - "title": "🇫🇷fr 🇨🇦ca: AdGuard Français", + "title": "🇫🇷fr 🇧🇪be 🇨🇦ca: AdGuard Français", "tags": "ads french", "lang": "ar br ff fr kab lb oc son", "contentURL": "https://filters.adtidy.org/extension/ublock/filters/16.txt", @@ -754,11 +754,11 @@ "content": "filters", "group": "regions", "off": true, - "title": "🇰🇷kr: List-KR Classic", + "title": "🇰🇷kr: 한국어 (Korean)", "tags": "ads korean 한국어", "lang": "ko", - "contentURL": "https://cdn.jsdelivr.net/npm/@list-kr/filterslists@latest/dist/filterslist-uBlockOrigin-classic.txt", - "supportURL": "https://github.com/List-KR/List-KR#readme" + "contentURL": "https://cdn.jsdelivr.net/npm/@filteringdev/filterslists-ko@latest/dist/filterslist-uBlockOrigin-classic.txt", + "supportURL": "https://github.com/FilteringDev/filterslists-KO#filteringdevfilterslists-ko" }, "LTU-0": { "content": "filters", diff --git a/dist/chromium/update-dev.xml b/dist/chromium/update-dev.xml new file mode 100644 index 0000000000000..34e90d1452398 --- /dev/null +++ b/dist/chromium/update-dev.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/dist/chromium/update.xml b/dist/chromium/update.xml new file mode 100644 index 0000000000000..ac29fcf913463 --- /dev/null +++ b/dist/chromium/update.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/dist/firefox/updates.json b/dist/firefox/updates.json index cb26b611cb849..2388343f971f0 100644 --- a/dist/firefox/updates.json +++ b/dist/firefox/updates.json @@ -3,13 +3,13 @@ "uBlock0@raymondhill.net": { "updates": [ { - "version": "1.70.1.0", + "version": "1.74.1.5", "browser_specific_settings": { "gecko": { "strict_min_version": "115.0" } }, - "update_link": "https://github.com/gorhill/uBlock/releases/download/1.70.1b0/uBlock0_1.70.1b0.firefox.signed.xpi" + "update_link": "https://github.com/gorhill/uBlock/releases/download/1.74.1b5/uBlock0_1.74.1b5.firefox.signed.xpi" } ] } diff --git a/dist/version b/dist/version index f8cca60bd6d24..452c76fe220e9 100644 --- a/dist/version +++ b/dist/version @@ -1 +1 @@ -1.70.1.5 \ No newline at end of file +1.74.1.6 \ No newline at end of file diff --git a/eslint.config.mjs b/eslint.config.mjs index f9bdca1ca9cd2..3a900ece58f95 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -18,8 +18,6 @@ export default [ includeIgnoreFile(gitignorePath), { languageOptions: { globals: { ...globals.browser, - browser: "readonly", - chrome: "readonly", vAPI: "readonly", }, sourceType: "module", diff --git a/platform/common/vapi-background.js b/platform/common/vapi-background.js index ff6ffd1e1f501..e4dc603b9b595 100644 --- a/platform/common/vapi-background.js +++ b/platform/common/vapi-background.js @@ -41,8 +41,6 @@ if ( vAPI.canWASM === false ) { vAPI.canWASM = csp !== undefined && csp.indexOf("'wasm-unsafe-eval'") !== -1; } -vAPI.supportsUserStylesheets = vAPI.webextFlavor.soup.has('user_stylesheet'); - /******************************************************************************/ vAPI.app = { @@ -342,14 +340,9 @@ vAPI.Tabs = class { } async insertCSS(tabId, details) { - if ( vAPI.supportsUserStylesheets ) { - details.cssOrigin = 'user'; - } - try { - await webext.tabs.insertCSS(...arguments); - } - catch { - } + details.cssOrigin = 'user'; + try { await webext.tabs.insertCSS(...arguments); } + catch { } } async query(queryInfo) { @@ -363,14 +356,9 @@ vAPI.Tabs = class { } async removeCSS(tabId, details) { - if ( vAPI.supportsUserStylesheets ) { - details.cssOrigin = 'user'; - } - try { - await webext.tabs.removeCSS(...arguments); - } - catch { - } + details.cssOrigin = 'user'; + try { await webext.tabs.removeCSS(...arguments); } + catch { } } // Properties of the details object: diff --git a/platform/common/vapi-common.js b/platform/common/vapi-common.js index 65e0c93c5c048..ae9f2d837d0ac 100644 --- a/platform/common/vapi-common.js +++ b/platform/common/vapi-common.js @@ -186,17 +186,27 @@ vAPI.webextFlavor = { flavor.isGecko = extensionOrigin.startsWith('moz-extension://'); if ( flavor.isGecko ) { soup.add('firefox') - .add('user_stylesheet') .add('html_filtering'); const match = /Firefox\/(\d+)/.exec(ua); flavor.major = match && parseInt(match[1], 10) || 115; } else { const match = /\bChrom(?:e|ium)\/(\d+)/.exec(ua); if ( match !== null ) { - soup.add('chromium') - .add('user_stylesheet'); + soup.add('chromium'); } flavor.major = match && parseInt(match[1], 10) || 120; + // Brave can't be told apart through the user agent string, which is + // identical to Chrome's. Both tests below are synchronous, whereas + // navigator.brave.isBrave() is promise-based -- the flavor must be + // settled before filter lists are compiled and cached. Either test + // alone would do, the second one is a fallback for the first. + // https://github.com/brave/brave-browser/wiki/Detecting-Brave-(for-Websites) + if ( + navigator.brave instanceof Object || + navigator.userAgentData?.brands?.some(a => a.brand === 'Brave') + ) { + soup.add('brave'); + } } // Don't starve potential listeners diff --git a/platform/mv3/README.md b/platform/mv3/README.md index 315821d47a7d3..7b2adb5a2cb6e 100644 --- a/platform/mv3/README.md +++ b/platform/mv3/README.md @@ -9,8 +9,8 @@ The following assumes a linux environment. 3. `cd uBlock` 4. `git submodule init` 5. `git submodule update` -6. `make mv3-[platform]`, where `[platform]` is either `chromium`, `edge`, `firefox`, or `safari` -7. This will fully build uBO Lite, and during the process filter lists will be downloaded from their respective remote servers +9. `make mv3-[platform]`, where `[platform]` is either `chromium`, `edge`, `firefox`, or `safari` +10. This will fully build uBO Lite, and during the process filter lists will be downloaded from their respective remote servers Upon completion of the script, the resulting extension package will become present in: diff --git a/platform/mv3/chromium/manifest.json b/platform/mv3/chromium/manifest.json index 091c0caf5ef07..0995341e2fdb6 100644 --- a/platform/mv3/chromium/manifest.json +++ b/platform/mv3/chromium/manifest.json @@ -42,10 +42,12 @@ "options_page": "dashboard.html", "permissions": [ "activeTab", + "alarms", "declarativeNetRequest", "offscreen", "scripting", "storage", + "unlimitedStorage", "userScripts" ], "short_name": "uBO Lite", diff --git a/platform/mv3/description/webstore.ar.txt b/platform/mv3/description/webstore.ar.txt index 459716f83ec6e..d65e29f633bfd 100644 --- a/platform/mv3/description/webstore.ar.txt +++ b/platform/mv3/description/webstore.ar.txt @@ -1,12 +1,12 @@ -uBO Lite (uBOL) هو مانع محتوى يعتمد على MV3. +uBO Lite (uBOL) هو أداة لحجب المحتوى تعتمد على MV3. -تتوافق مجموعة القواعد الافتراضية مع مجموعة عوامل التصفية الافتراضية لـ uBlock Origin: +تتوافق مجموعة القواعد الافتراضية مع مجموعة خيارات التصفية الافتراضية لـ uBlock Origin: -- قوائم التصفية المدمجة في uBlock Origin -- القائمة السهلة -- الخصوصية السهلة -- قائمة خادم الإعلانات والتتبع لبيتر لوي +- قوائم خيارات التصفية المدمجة في uBlock Origin +- EasyList +- EasyPrivacy +- قائمة خادم الإعلانات والتتبع لـ Peter Lowe -يمكنك تفعيل المزيد من مجموعات القواعد من خلال زيارة صفحة الخيارات - انقر على أيقونة _الترس_ في لوحة الإشعارات. +← يمكنك تفعيل المزيد من مجموعات القواعد بزيارة صفحة الخيارات – انقر على أيقونة _الترس_ في اللوحة المنبثقة. -uBOL صريح تمامًا، مما يعني أنه لا تحتاج إلى uBOL بشكل دائم لحدوث تصفية المحتوى، يتم إجراء تصفية المحتوى من خلال إضافة CSS/JS بشكل موثوق به بواسطة المتصفح نفسه بدلًا من الإضافة. هذا يعني أن uBOL نفسه لا يستهلك موارد وحدة المعالجة المركزية/الذاكرة أثناء استمراره في حظر المحتوى. +يعد uBOL نظاما تصريحيا بالكامل، مما يعني أنه لا توجد حاجة إلى عملية uBOL دائمة لإجراء التصفية، كما أن تصفية المحتوى القائمة على حقن CSS/JS تتم بشكل موثوق بواسطة المتصفح نفسه وليس بواسطة الملحق. وهذا يعني أن uBOL نفسه لا يستهلك موارد وحدة المعالجة المركزية أو الذاكرة أثناء عملية حجب المحتوى — لا تكون عملية «service worker» الخاصة بـ uBOL مطلوبة _إلا_ عند التفاعل مع اللوحة المنبثقة أو صفحات الخيارات. diff --git a/platform/mv3/description/webstore.az.txt b/platform/mv3/description/webstore.az.txt index 9f232d8bdf34e..a4648bb6f860a 100644 --- a/platform/mv3/description/webstore.az.txt +++ b/platform/mv3/description/webstore.az.txt @@ -1,4 +1,4 @@ -uBO Lite (uBOL) is an MV3-based content blocker. +uBO Lite (uBOL) MV3 əsaslı məzmun bloklayıcısıdır. Defolt qaydalar dəsti uBlock Origin-in defolt filtr dəstinə uyğundur: @@ -7,6 +7,6 @@ Defolt qaydalar dəsti uBlock Origin-in defolt filtr dəstinə uyğundur: - EasyPrivacy - Peter Lowe-un Reklam və izləyici server siyahısı -You can enable more rulesets by visiting the options page -- click the _Cogs_ icon in the popup panel. +Seçimlər səhifəsinə keçərək daha çox qayda dəstini aktivləşdirə bilərsiniz. Bunun üçün açılan paneldəki _Dişli çarxlar_ ikonasına klikləyin. -uBOL is entirely declarative, meaning there is no need for a permanent uBOL process for the filtering to occur, and CSS/JS injection-based content filtering is performed reliably by the browser itself rather than by the extension. Bu sistemin köməyi ilə, uBOL prosessorunuzu və yaddaşınızı qətiyyən yormur. Proqramın arxa fon prosesi (service worker) yalnız siz idarəetmə paneli və ya parametrlər səhifəsini açanda işə düşür. +uBOL tamamilə deklarativdir. Bu o deməkdir ki, filtrləmənin aparılması üçün uBOL-un daimi prosesinə ehtiyac yoxdur və CSS/JS inyeksiyasına əsaslanan məzmun filtrləməsi genişləndirmə əvəzinə birbaşa brauzer tərəfindən etibarlı şəkildə həyata keçirilir. Bu sistemin köməyi ilə, uBOL prosessorunuzu və yaddaşınızı qətiyyən yormur. Proqramın arxa fon prosesi (service worker) yalnız siz idarəetmə paneli və ya parametrlər səhifəsini açanda işə düşür. diff --git a/platform/mv3/description/webstore.cy.txt b/platform/mv3/description/webstore.cy.txt index 056c49a64ca7d..27c06e37a1845 100644 --- a/platform/mv3/description/webstore.cy.txt +++ b/platform/mv3/description/webstore.cy.txt @@ -1,12 +1,12 @@ -uBO Lite (uBOL) is an MV3-based content blocker. +Mae uBO Lite (uBOL) yn rwystrydd cynnwys sy'n seiliedig ar MV3. Mae'r set reolau ddiofyn yn cyfateb i set hidlo diofyn uBlock Origin: -- uBlock Origin's built-in filter lists +- rhestrau hidl adeiledig uBlock Origin - EasyList - EasyPrivacy - Peter Lowe’s Ad and tracking server list -You can enable more rulesets by visiting the options page -- click the _Cogs_ icon in the popup panel. +Gallwch alluogi mwy o setiau rheolau trwy ymweld â'r dudalen opsiynau -- cliciwch yr eicon _Gears_ yn y panel naid. -uBOL is entirely declarative, meaning there is no need for a permanent uBOL process for the filtering to occur, and CSS/JS injection-based content filtering is performed reliably by the browser itself rather than by the extension. This means that uBOL itself does not consume CPU/memory resources while content blocking is ongoing -- uBOL's service worker process is required _only_ when you interact with the popup panel or the option pages. +Mae uBOL yn gwbl ddatganiadol, sy'n golygu nad oes angen proses uBOL barhaol ar gyfer hidlo, ac mae hidlo cynnwys sy'n seiliedig ar chwistrelliad CSS/JS yn cael ei berfformio'n ddibynadwy gan y porwr ei hun yn hytrach na chan yr estyniad. Mae hyn yn golygu nad yw uBOL ei hun yn defnyddio adnoddau CPU/cof tra bod blocio cynnwys yn mynd rhagddo -- dim ond pan fyddwch yn rhyngweithio â'r panel naid neu'r tudalennau opsiynau y mae angen proses gweithiwr gwasanaeth uBOL. diff --git a/platform/mv3/description/webstore.el.txt b/platform/mv3/description/webstore.el.txt index cd53ddda9c789..5f3f252d4b5d6 100644 --- a/platform/mv3/description/webstore.el.txt +++ b/platform/mv3/description/webstore.el.txt @@ -1,4 +1,4 @@ -Το uBO Lite (uBOL) είναι εργαλείο φραγής περιεχομένου βασισμένο στο MV3. +Το uBO Lite (uBOL) είναι εργαλείο αποκλεισμού περιεχομένου βασισμένο στο MV3. Το προεπιλεγμένο σύνολο κανόνων αντιστοιχεί στο προεπιλεγμένο σύνολο φίλτρων του uBlock Origin: diff --git a/platform/mv3/description/webstore.eo.txt b/platform/mv3/description/webstore.eo.txt index ef089202b9565..11cc8fbe7a87e 100644 --- a/platform/mv3/description/webstore.eo.txt +++ b/platform/mv3/description/webstore.eo.txt @@ -1,12 +1,12 @@ -uBO Lite (uBOL) is an MV3-based content blocker. +uBO Lite (uBOL) estas per-MV3 reklamoblokilo. -The default ruleset corresponds to uBlock Origin's default filterset: +La norma regularo kongruas kun la sama de uBlock Origin: -- uBlock Origin's built-in filter lists +- Kunigitaj filtriloj de uBlock Origin - EasyList - EasyPrivacy -- Peter Lowe’s Ad and tracking server list +- Listo de serviloj kun reklamoj kaj spuriloj, de Peter Lowe -You can enable more rulesets by visiting the options page -- click the _Cogs_ icon in the popup panel. +Vi povas ŝalti pli regularojn per la agorda paĝo -- alklaku la bildsimbolon de dento-radoj en la ŝprucfenestro. -uBOL is entirely declarative, meaning there is no need for a permanent uBOL process for the filtering to occur, and CSS/JS injection-based content filtering is performed reliably by the browser itself rather than by the extension. This means that uBOL itself does not consume CPU/memory resources while content blocking is ongoing -- uBOL's service worker process is required _only_ when you interact with the popup panel or the option pages. +uBOL estas tute indika, signifante ke la uBOL proceso ne bezonatas por filtri, kaj filtradon per aldonado de CSS/JS faras la retumilo mem anstataŭ la kromprogramo. Tiu ĉi signifas ke uBOL mem ne uzas rimedojn de la ĉefprocesoro aŭ memoro dum blokado -- la procezo de uBOL postuliĝas nur kiam vi uzas la ŝprucfenestron aŭ la agordajn paĝojn. diff --git a/platform/mv3/description/webstore.eu.txt b/platform/mv3/description/webstore.eu.txt index f2373f6895b53..504b9de6b8fbe 100644 --- a/platform/mv3/description/webstore.eu.txt +++ b/platform/mv3/description/webstore.eu.txt @@ -1,4 +1,4 @@ -uBO Lite (uBOL) is an MV3-based content blocker. +uBO Lite (uBOL) MV3-n oinarritutako edukien blokeatzailea da. Lehenespenez, iragazki-zerrenda hauek ditu konfiguratuta: diff --git a/platform/mv3/description/webstore.fa.txt b/platform/mv3/description/webstore.fa.txt index c455fdc90983a..d07335bac0c2f 100644 --- a/platform/mv3/description/webstore.fa.txt +++ b/platform/mv3/description/webstore.fa.txt @@ -1,12 +1,12 @@ -uBO Lite (uBOL) is an MV3-based content blocker. +uBO Lite (uBOL) یک مسدودکننده محتوا بر پایه MV3 است. مجموعه قوانین پیش فرض آن مطابق با مجموعه قوانین پیش فرض uBlock Origin است: -- uBlock Origin's built-in filter lists +- لیست‌های فیلتر داخلی uBlock Origin - EasyList - EasyPrivacy -- Peter Lowe’s Ad and tracking server list +- لیست سرورهای تبلیغاتی و ردیابی Peter Lowe -You can enable more rulesets by visiting the options page -- click the _Cogs_ icon in the popup panel. +شما می‌توانید با مراجعه به صفحه گزینه‌ها، مجموعه قوانین بیشتری را فعال کنید - روی آیکون _چرخ‌دنده_ در پنل بازشو کلیک کنید. -uBOL is entirely declarative, meaning there is no need for a permanent uBOL process for the filtering to occur, and CSS/JS injection-based content filtering is performed reliably by the browser itself rather than by the extension. This means that uBOL itself does not consume CPU/memory resources while content blocking is ongoing -- uBOL's service worker process is required _only_ when you interact with the popup panel or the option pages. +uBOL کاملاً اعلامی است، به این معنی که برای انجام فیلتر کردن نیازی به یک فرآیند دائمی uBOL نیست و فیلتر کردن محتوا بر پایه تزریق CSS/JS به طور قابل اعتمادی توسط خود مرورگر به جای افزونه انجام می‌شود. این بدان معناست که خود uBOL در حین مسدودسازی محتوا منابع CPU/حافظه را مصرف نمی‌کند - فرآیند کارگر سرویس uBOL _فقط_ زمانی مورد نیاز است که شما با پنل بازشو یا صفحات گزینه‌ها تعامل داشته باشید. diff --git a/platform/mv3/description/webstore.gu.txt b/platform/mv3/description/webstore.gu.txt index ef089202b9565..5e5454d5b0339 100644 --- a/platform/mv3/description/webstore.gu.txt +++ b/platform/mv3/description/webstore.gu.txt @@ -1,12 +1,12 @@ -uBO Lite (uBOL) is an MV3-based content blocker. +uBO Lite (uBOL) એ MV3-આધારિત સામગ્રી અવરોધક છે. -The default ruleset corresponds to uBlock Origin's default filterset: +મૂળભૂત નિયમસમૂહ uBlock Origin ના મૂળભૂત ફિલ્ટરસમૂહને અનુરૂપ છે: -- uBlock Origin's built-in filter lists +- uBlock Origin ની બિલ્ટ-ઇન ફિલ્ટર યાદીઓ - EasyList - EasyPrivacy -- Peter Lowe’s Ad and tracking server list +- Peter Lowe's જાહેરાત અને ટ્રૅકિંગ સર્વર યાદી -You can enable more rulesets by visiting the options page -- click the _Cogs_ icon in the popup panel. +તમે વિકલ્પો પેજની મુલાકાત લઈને વધુ નિયમસમૂહો સક્ષમ કરી શકો છો -- પોપઅપ પેનલમાં _Cogs_ આઇકન પર ક્લિક કરો. -uBOL is entirely declarative, meaning there is no need for a permanent uBOL process for the filtering to occur, and CSS/JS injection-based content filtering is performed reliably by the browser itself rather than by the extension. This means that uBOL itself does not consume CPU/memory resources while content blocking is ongoing -- uBOL's service worker process is required _only_ when you interact with the popup panel or the option pages. +uBOL સંપૂર્ણપણે ઘોષણાત્મક છે, એટલે કે ફિલ્ટરિંગ થવા માટે કાયમી uBOL પ્રક્રિયાની જરૂર નથી, અને CSS/JS ઇન્જેક્શન-આધારિત સામગ્રી ફિલ્ટરિંગ એક્સ્ટેંશન દ્વારા નહીં પરંતુ બ્રાઉઝર દ્વારા જ વિશ્વસનીય રીતે કરવામાં આવે છે. આનો અર્થ એ છે કે સામગ્રી અવરોધ ચાલુ હોય ત્યારે uBOL પોતે CPU/મેમરી સંસાધનોનો ઉપયોગ કરતું નથી -- uBOL ની સર્વિસ વર્કર પ્રક્રિયા _માત્ર_ જ્યારે તમે પોપઅપ પેનલ અથવા વિકલ્પો પેજો સાથે સંપર્ક કરો છો ત્યારે જરૂરી છે. diff --git a/platform/mv3/description/webstore.hy.txt b/platform/mv3/description/webstore.hy.txt index 75522194eb932..fe21760b6dee1 100644 --- a/platform/mv3/description/webstore.hy.txt +++ b/platform/mv3/description/webstore.hy.txt @@ -1,4 +1,4 @@ -uBO Lite (uBOL) is an MV3-based content blocker. +uBO Lite-ը (uBOL) MV3-ի վրա հիմնված բովանդակության արգելափակիչ է։ Կանոնների լռելյայն փաթեթը համապատասխանում է uBlock Origin-ի լռելյայն զտիչների փաթեթին։ @@ -7,6 +7,6 @@ uBO Lite (uBOL) is an MV3-based content blocker. - EasyPrivacy - Peter Lowe-ի գովազդային և հետագծող սպասարկիչների ցուցակ -You can enable more rulesets by visiting the options page -- click the _Cogs_ icon in the popup panel. +Դուք կարող եք միացնել ավելի շատ կանոնների հավաքածուներ՝ այցելելով կարգավորումների էջ -- սեղմեք _Ատամնանիվ_ պատկերակը թռուցիկ վահանակում։ uBOL-ն ամբողջությամբ դեկլարատիվ է, այսինքն՝ զտման համար անընդհատ կատարվող uBOL գործընթացի կարիք չկա, իսկ CSS/JS արմատավորման վրա հիմնված բովանդակության զտումը հուսալիորեն իրականացվում է զննիչի կողմից, այլ ոչ թե ընդլայնման միջոցով։ Սա նշանակում է, որ uBOL հավելումը չի սպառում մշակիչի/հիշողության որևէ ռեսուրս, երբ տեղի է ունենում գովազդի արգելափակումը. uBOL աշխատանքային գործընթացն աշխատում է _միայն_ երբ Դուք փոփոխություններ եք կատարում դուրս լողացող վահանակում կամ ընտրանքների էջում։ diff --git a/platform/mv3/description/webstore.kn.txt b/platform/mv3/description/webstore.kn.txt index da1d83d7965ed..50e240b540712 100644 --- a/platform/mv3/description/webstore.kn.txt +++ b/platform/mv3/description/webstore.kn.txt @@ -1,12 +1,12 @@ -uBO Lite (uBOL) is an MV3-based content blocker. +uBO Lite (uBOL) ಒಂದು MV3-ಆಧಾರಿತ ವಿಷಯ ನಿರ್ಬಂಧಕವಾಗಿದೆ. -The default ruleset corresponds to uBlock Origin's default filterset: +ಡೀಫಾಲ್ಟ್ ನಿಯಮಗಳ ಗುಂಪು uBlock Origin ನ ಡೀಫಾಲ್ಟ್ ಶೋಧಕ ಗುಂಪಿಗೆ ಅನುರೂಪವಾಗಿದೆ: -- uBlock Origin's built-in filter lists +- uBlock Origin ನ ಅಂತರ್ನಿರ್ಮಿತ ಶೋಧಕ ಪಟ್ಟಿಗಳು - EasyList - EasyPrivacy -- Peter Lowe’s Ad and tracking server list +- ಪೀಟರ್ ಲೋ ಅವರ ಜಾಹೀರಾತು ಮತ್ತು ಟ್ರ್ಯಾಕಿಂಗ್ ಸರ್ವರ್ ಪಟ್ಟಿ -You can enable more rulesets by visiting the options page -- click the _Cogs_ icon in the popup panel. +ಆಯ್ಕೆಗಳ ಪುಟಕ್ಕೆ ಭೇಟಿ ನೀಡುವ ಮೂಲಕ ನೀವು ಹೆಚ್ಚಿನ ನಿಯಮಗಳ ಗುಂಪುಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಬಹುದು -- ಪಾಪಪ್ ಫಲಕದಲ್ಲಿ _ಗೇರ್ಗಳ_ ಐಕಾನ್ ಅನ್ನು ಕ್ಲಿಕ್ ಮಾಡಿ. -uBOL is entirely declarative, meaning there is no need for a permanent uBOL process for the filtering to occur, and CSS/JS injection-based content filtering is performed reliably by the browser itself rather than by the extension. ಇದರರ್ಥ ವಿಷಯ ನಿರ್ಬಂಧಿಸುವಿಕೆಯು ನಡೆಯುತ್ತಿರುವಾಗ uBOL ಸ್ವತಃ CPU/ಮೆಮೊರಿ ಸಂಪನ್ಮೂಲಗಳನ್ನು ಬಳಸುವುದಿಲ್ಲ -- ನೀವು ಪಾಪ್ಅಪ್ ಪ್ಯಾನೆಲ್ ಅಥವಾ ಆಯ್ಕೆಯ ಪುಟಗಳೊಂದಿಗೆ ಸಂವಹನ ನಡೆಸಿದಾಗ uBOL ನ ಸೇವಾ ವರ್ಕರ್ ಪ್ರಕ್ರಿಯೆಯು _ಮಾತ್ರಾ_ ಅಗತ್ಯವಿದೆ. +uBOL ಸಂಪೂರ್ಣವಾಗಿ ಘೋಷಣಾತ್ಮಕವಾಗಿದೆ, ಅಂದರೆ ಶೋಧನೆ ನಡೆಯಲು ಶಾಶ್ವತ uBOL ಪ್ರಕ್ರಿಯೆಯ ಅಗತ್ಯವಿಲ್ಲ, ಮತ್ತು CSS/JS ಇಂಜೆಕ್ಷನ್-ಆಧಾರಿತ ವಿಷಯ ಶೋಧನೆಯನ್ನು ವಿಸ್ತರಣೆಯ ಬದಲಿಗೆ ಬ್ರೌಸರ್ ಸ್ವತಃ ವಿಶ್ವಾಸಾರ್ಹವಾಗಿ ನಿರ್ವಹಿಸುತ್ತದೆ. ಇದರರ್ಥ ವಿಷಯ ನಿರ್ಬಂಧಿಸುವಿಕೆಯು ನಡೆಯುತ್ತಿರುವಾಗ uBOL ಸ್ವತಃ CPU/ಮೆಮೊರಿ ಸಂಪನ್ಮೂಲಗಳನ್ನು ಬಳಸುವುದಿಲ್ಲ -- ನೀವು ಪಾಪ್ಅಪ್ ಪ್ಯಾನೆಲ್ ಅಥವಾ ಆಯ್ಕೆಯ ಪುಟಗಳೊಂದಿಗೆ ಸಂವಹನ ನಡೆಸಿದಾಗ uBOL ನ ಸೇವಾ ವರ್ಕರ್ ಪ್ರಕ್ರಿಯೆಯು _ಮಾತ್ರಾ_ ಅಗತ್ಯವಿದೆ. diff --git a/platform/mv3/description/webstore.ko.txt b/platform/mv3/description/webstore.ko.txt index cf38909f3f33c..8a836cd7e1fee 100644 --- a/platform/mv3/description/webstore.ko.txt +++ b/platform/mv3/description/webstore.ko.txt @@ -1,12 +1,12 @@ -uBO Lite (uBOL)는 MV3 기반 콘텐츠 차단기입니다. +uBO Lite(uBOL)는 MV3 기반 콘텐츠 차단기입니다. -기본 규칙 목록은 uBlock Origin의 기본 필터 목록과 대응됩니다. +기본 규칙 목록은 uBlock Origin의 기본 필터 목록과 동일합니다: - uBlock Origin 내장 필터 목록 - EasyList - EasyPrivacy - Peter Lowe’s Ad and tracking server list -설정 페이지에서 규칙 목록을 더 활성화할 수 있습니다. 팝업 창의 _Cogs_ 아이콘을 누르세요. +팝업 패널에서 톱니바퀴 아이콘을 클릭하여 옵션 페이지로 이동하면 더 많은 규칙 목록을 활성화할 수 있습니다. -uBOL은 완전히 선언적이라 필터링 중 영구적으로 실행되는 uBOL 프로세스를 필요로 하지 않으며, CSS/JS 주입 기반 콘텐츠 필터링이 확장 프로그램이 아닌 브라우저 자체에서 더욱 안정적으로 동작합니다. 이는 콘텐츠 차단이 진행되는 동안 uBOL 자체는 CPU나 메모리 자원을 소모하지 않음을 의미합니다. uBOL의 서비스 워커 프로세스는 팝업 창이나 설정을 사용할 때만 실행됩니다. +uBOL은 완전한 선언형 방식으로 작동합니다. 즉, 필터링을 위해 uBOL 프로세스를 상시 실행할 필요가 없으며, CSS/JS 주입 기반 콘텐츠 필터링은 확장 프로그램이 아닌 브라우저 자체가 직접 안정적으로 수행합니다. 따라서 콘텐츠 차단이 진행되는 동안 uBOL 자체는 CPU/메모리 자원을 소비하지 않습니다. uBOL의 서비스 워커 프로세스는 팝업 패널이나 옵션 페이지를 조작할 때만 실행됩니다. diff --git a/platform/mv3/description/webstore.lt.txt b/platform/mv3/description/webstore.lt.txt index ef089202b9565..847ef5fc88ca8 100644 --- a/platform/mv3/description/webstore.lt.txt +++ b/platform/mv3/description/webstore.lt.txt @@ -1,12 +1,12 @@ -uBO Lite (uBOL) is an MV3-based content blocker. +uBO Lite (uBOL) yra MV3 pagrindu veikiantis turinio blokatorius. -The default ruleset corresponds to uBlock Origin's default filterset: +Numatytasis taisyklių rinkinys atitinka uBlock Origin numatytąjį filtrų rinkinį: -- uBlock Origin's built-in filter lists +- įtaisytieji uBlock Origin filtrų sąrašai - EasyList - EasyPrivacy -- Peter Lowe’s Ad and tracking server list +- Peter Lowe reklamos ir sekimo serverių sąrašas -You can enable more rulesets by visiting the options page -- click the _Cogs_ icon in the popup panel. +Daugiau taisyklių rinkinių galite įjungti apsilankę parinkčių puslapyje – spustelėkite _krumpliaračių_ piktogramą iškylančiame skydelyje. -uBOL is entirely declarative, meaning there is no need for a permanent uBOL process for the filtering to occur, and CSS/JS injection-based content filtering is performed reliably by the browser itself rather than by the extension. This means that uBOL itself does not consume CPU/memory resources while content blocking is ongoing -- uBOL's service worker process is required _only_ when you interact with the popup panel or the option pages. +uBOL yra visiškai deklaratyvus, o tai reiškia, kad filtravimui nereikia nuolatinio uBOL proceso, o CSS/JS injekcijomis pagrįstą turinio filtravimą patikimai atlieka pati naršyklė, o ne plėtinys. Tai reiškia, kad pats uBOL nenaudoja procesoriaus / atminties išteklių, kol vyksta turinio blokavimas – uBOL paslaugų darbuotojo procesas reikalingas _tik_ tada, kai sąveikaujate su iškylančiuoju skydeliu arba parinkčių puslapiais. diff --git a/platform/mv3/description/webstore.mk.txt b/platform/mv3/description/webstore.mk.txt index de9010a73fc69..b17948c60e395 100644 --- a/platform/mv3/description/webstore.mk.txt +++ b/platform/mv3/description/webstore.mk.txt @@ -1,4 +1,4 @@ -uBO Lite (uBOL) is an MV3-based content blocker. +uBO Lite (uBOL) е блокатор на содржини базиран на MV3. Стандардниот сет на правила одговара на стандардниот филтер сет на uBlock Origin: diff --git a/platform/mv3/description/webstore.ml.txt b/platform/mv3/description/webstore.ml.txt index f151132e6a5cc..e6ec10f1105a5 100644 --- a/platform/mv3/description/webstore.ml.txt +++ b/platform/mv3/description/webstore.ml.txt @@ -1,4 +1,4 @@ -uBO Lite (uBOL) is an MV3-based content blocker. +uBO Lite (uBOL) ഒരു MV3 അടിസ്ഥാനമാക്കിയുള്ള ഉള്ളടക്ക ബ്ലോക്കറാണ്. ഡിഫോൾട്ട് റൂൾസെറ്റ് uBlock Origin-ന്റെ ഡിഫോൾട്ട് ഫിൽട്ടർസെറ്റുമായി യോജിക്കുന്നു: @@ -7,6 +7,6 @@ uBO Lite (uBOL) is an MV3-based content blocker. - ഈസി സ്വകാര്യത - പീറ്റർ ലോവിന്റെ പരസ്യവും ട്രാക്കിംഗ് സെർവർ ലിസ്റ്റും -You can enable more rulesets by visiting the options page -- click the _Cogs_ icon in the popup panel. +ഓപ്ഷനുകൾ പേജ് സന്ദർശിച്ചുകൊണ്ട് നിങ്ങൾക്ക് കൂടുതൽ റൂൾസെറ്റുകൾ പ്രവർത്തനക്ഷമമാക്കാം -- പോപ്പപ്പ് പാനലിലെ _Cogs_ ഐക്കൺ ക്ലിക്ക് ചെയ്യുക. uBOL പൂർണ്ണമായും ഡിക്ലറേറ്റീവ് ആണ്, അതായത് ഫിൽട്ടറിംഗ് സംഭവിക്കുന്നതിന് ഒരു സ്ഥിരമായ uBOL പ്രക്രിയയുടെ ആവശ്യമില്ല, കൂടാതെ CSS/JS ഇഞ്ചക്ഷൻ അടിസ്ഥാനമാക്കിയുള്ള ഉള്ളടക്ക ഫിൽട്ടറിംഗ്, എക്സ്റ്റൻഷനേക്കാൾ വിശ്വസനീയമായി ബ്രൗസർ തന്നെ നിർവഹിക്കുന്നു. ഉള്ളടക്കം തടയൽ നടന്നുകൊണ്ടിരിക്കുമ്പോൾ uBOL തന്നെ CPU/മെമ്മറി ഉറവിടങ്ങൾ ഉപയോഗിക്കില്ല എന്നാണ് ഇതിനർത്ഥം -- നിങ്ങൾ പോപ്പ്അപ്പ് പാനലുമായോ ഓപ്‌ഷൻ പേജുകളുമായോ സംവദിക്കുമ്പോൾ _only_ uBOL-ന്റെ സേവന വർക്കർ പ്രോസസ്സ് ആവശ്യമാണ്. diff --git a/platform/mv3/description/webstore.ms.txt b/platform/mv3/description/webstore.ms.txt index 7b4301bcaa2e4..3cf2d2d6bc997 100644 --- a/platform/mv3/description/webstore.ms.txt +++ b/platform/mv3/description/webstore.ms.txt @@ -1,4 +1,4 @@ -uBO Lite (uBOL) is an MV3-based content blocker. +uBO Lite (uBOL) ialah penyekat kandungan berasaskan MV3. Set peraturan lalai sepadan dengan set penapis lalai uBlock Origin: diff --git a/platform/mv3/description/webstore.oc.txt b/platform/mv3/description/webstore.oc.txt index ef089202b9565..e88211fc9f7a2 100644 --- a/platform/mv3/description/webstore.oc.txt +++ b/platform/mv3/description/webstore.oc.txt @@ -1,12 +1,12 @@ -uBO Lite (uBOL) is an MV3-based content blocker. +uBO Lite (uBOL) es un blocaire de contengut basat sus MV3. -The default ruleset corresponds to uBlock Origin's default filterset: +Lo jòc de règlas per defaut correspond al jòc de filtres per defaut d'uBlock Origin: -- uBlock Origin's built-in filter lists +- Listas de filtres integradas d'uBlock Origin - EasyList - EasyPrivacy -- Peter Lowe’s Ad and tracking server list +- Lista dels servidors publicitaris e de seguiment de Peter Lowe -You can enable more rulesets by visiting the options page -- click the _Cogs_ icon in the popup panel. +Podètz activar mai de jòcs de règlas en visitant la pagina de las opcions -- clicar sus l'icòna _Engranatges_ dins lo panèl sorgissent. -uBOL is entirely declarative, meaning there is no need for a permanent uBOL process for the filtering to occur, and CSS/JS injection-based content filtering is performed reliably by the browser itself rather than by the extension. This means that uBOL itself does not consume CPU/memory resources while content blocking is ongoing -- uBOL's service worker process is required _only_ when you interact with the popup panel or the option pages. +uBOL es entièrament declaratiu, çò que significa que i a pas besonh d'un processus uBOL permanent per que lo filtratge se debane, e que lo filtratge de contengut basat sus l'injeccion CSS/JS es realizat de biais fisable pel navigador meteis puslèu que per l'extension. Aquò significa que uBOL meteis consumís pas de ressorsas CPU/memòria mentre lo blocatge de contengut es en cors -- lo processus service worker d'uBOL es requerit _solament_ quand interagissètz amb lo panèl sorgissent o las paginas d'opcions. diff --git a/platform/mv3/description/webstore.pa.txt b/platform/mv3/description/webstore.pa.txt index a702d4dde8ded..572fbb4319343 100644 --- a/platform/mv3/description/webstore.pa.txt +++ b/platform/mv3/description/webstore.pa.txt @@ -9,4 +9,4 @@ uBO Lite (uBOL) ਇੱਕ MV3-ਅਧਾਰਿਤ ਸਮੱਗਰੀ ਬਲਾਕ ਤੁਸੀਂ ਚੋਣਾਂ ਸਫ਼ੇ ਨੂੰ ਖੋਲ੍ਹ ਕੇ ਹੋਰ ਰੂਲ-ਸੈੱਟ ਸਮਰੱਥ ਕਰ ਕਦੇ ਹੋ -- ਪੌਪ-ਅੱਪ ਪੈਨਲ ਵਿੱਚ _Cogs_ icon ਨੂੰ ਕਲਿੱਕ ਕਰੋ। -uBOL is entirely declarative, meaning there is no need for a permanent uBOL process for the filtering to occur, and CSS/JS injection-based content filtering is performed reliably by the browser itself rather than by the extension. This means that uBOL itself does not consume CPU/memory resources while content blocking is ongoing -- uBOL's service worker process is required _only_ when you interact with the popup panel or the option pages. +uBOL ਪੂਰੀ ਤਰ੍ਹਾਂ ਘੋਸ਼ਣਾਤਮਕ ਹੈ, ਭਾਵ ਫਿਲਟਰਿੰਗ ਹੋਣ ਲਈ ਇੱਕ ਸਥਾਈ uBOL ਪ੍ਰਕਿਰਿਆ ਦੀ ਕੋਈ ਲੋੜ ਨਹੀਂ ਹੈ, ਅਤੇ CSS/JS ਇੰਜੈਕਸ਼ਨ-ਅਧਾਰਿਤ ਸਮੱਗਰੀ ਫਿਲਟਰਿੰਗ ਐਕਸਟੈਂਸ਼ਨ ਦੁਆਰਾ ਨਹੀਂ ਸਗੋਂ ਖੁਦ ਬ੍ਰਾਊਜ਼ਰ ਦੁਆਰਾ ਭਰੋਸੇਯੋਗ ਢੰਗ ਨਾਲ ਕੀਤੀ ਜਾਂਦੀ ਹੈ। ਇਸਦਾ ਮਤਲਬ ਹੈ ਕਿ uBOL ਖੁਦ ਸਮੱਗਰੀ ਬਲਾਕਿੰਗ ਜਾਰੀ ਰਹਿਣ ਦੌਰਾਨ CPU/ਮੈਮਰੀ ਸਰੋਤਾਂ ਦੀ ਖਪਤ ਨਹੀਂ ਕਰਦਾ -- uBOL ਦੀ ਸਰਵਿਸ ਵਰਕਰ ਪ੍ਰਕਿਰਿਆ ਦੀ ਲੋੜ _ਸਿਰਫ_ ਉਦੋਂ ਹੁੰਦੀ ਹੈ ਜਦੋਂ ਤੁਸੀਂ ਪੌਪਅੱਪ ਪੈਨਲ ਜਾਂ ਵਿਕਲਪ ਪੰਨਿਆਂ ਨਾਲ ਗੱਲਬਾਤ ਕਰਦੇ ਹੋ। diff --git a/platform/mv3/description/webstore.sl.txt b/platform/mv3/description/webstore.sl.txt index ef089202b9565..3734a6a43874e 100644 --- a/platform/mv3/description/webstore.sl.txt +++ b/platform/mv3/description/webstore.sl.txt @@ -1,12 +1,12 @@ -uBO Lite (uBOL) is an MV3-based content blocker. +uBO Lite (uBOL) je blokator vsebin, ki temelji na MV3. -The default ruleset corresponds to uBlock Origin's default filterset: +Privzeti sklop pravil ustreza privzetemu sklopu filtrov uBlock Origin: -- uBlock Origin's built-in filter lists +- Vgrajeni seznami filtrov uBlock Origin - EasyList - EasyPrivacy -- Peter Lowe’s Ad and tracking server list +- Seznam oglasnih in sledilnih strežnikov Petra Loweja -You can enable more rulesets by visiting the options page -- click the _Cogs_ icon in the popup panel. +Več sklopov pravil lahko omogočite z obiskom strani z možnostmi -- kliknite ikono _Zobnikov_ v pojavni plošči. -uBOL is entirely declarative, meaning there is no need for a permanent uBOL process for the filtering to occur, and CSS/JS injection-based content filtering is performed reliably by the browser itself rather than by the extension. This means that uBOL itself does not consume CPU/memory resources while content blocking is ongoing -- uBOL's service worker process is required _only_ when you interact with the popup panel or the option pages. +uBOL je v celoti deklarativen, kar pomeni, da za filtriranje ni potreben stalen proces uBOL, filtriranje vsebin na podlagi injiciranja CSS/JS pa zanesljivo izvaja sam brskalnik in ne razširitev. To pomeni, da uBOL sam ne porablja virov CPU/pomnilnika med potekajočim blokiranjem vsebin -- proces storitvenega delavca uBOL je potreben _samo_, ko komunicirate s pojavno ploščo ali stranmi z možnostmi. diff --git a/platform/mv3/description/webstore.so.txt b/platform/mv3/description/webstore.so.txt index ef089202b9565..0df0ddc086e81 100644 --- a/platform/mv3/description/webstore.so.txt +++ b/platform/mv3/description/webstore.so.txt @@ -1,12 +1,12 @@ -uBO Lite (uBOL) is an MV3-based content blocker. +uBO Lite (uBOL) waa xannibaade waxyaabo ku saleysan MV3. -The default ruleset corresponds to uBlock Origin's default filterset: +Xeerarka goobjoogga ah waxay u dhigmaan shaandhaha goobjoogga ah ee uBlock Origin: -- uBlock Origin's built-in filter lists +- Liisaska shaandhada ee ku dhisan uBlock Origin - EasyList - EasyPrivacy -- Peter Lowe’s Ad and tracking server list +- Liiska Server-yada Xayeysiiska iyo Raad-raaca ee Peter Lowe -You can enable more rulesets by visiting the options page -- click the _Cogs_ icon in the popup panel. +Waxaad ku dari kartaa xeerar badan adigoo booqanaya bogga ikhtiyaarrada -- guji astaanta _Cogs_ ee ku taal popup-ka. -uBOL is entirely declarative, meaning there is no need for a permanent uBOL process for the filtering to occur, and CSS/JS injection-based content filtering is performed reliably by the browser itself rather than by the extension. This means that uBOL itself does not consume CPU/memory resources while content blocking is ongoing -- uBOL's service worker process is required _only_ when you interact with the popup panel or the option pages. +uBOL gabi ahaanba waa mid ku saleysan ku dhawaaqid, taasoo la macno ah inaan loo baahnayn hawleed joogto ah oo uBOL ah si shaandhayntu u dhacdo, shaandhaynta waxyaabaha ku saleysan CSS/JS injection waxaa si isku halayn ah u fuliya biraawsarka laftiisa halkii uu ka fulin lahaa kordhinta. Tani waxay ka dhigan tahay in uBOL lafteedu aysan isticmaalin kheyraadka CPU/xusuusta inta xannibaadda waxyaabaha socoto -- hawsha service worker ee uBOL waxaa loo baahan yahay _kaliya_ markaad la falgasho popup-ka ama bogagga ikhtiyaarrada. diff --git a/platform/mv3/description/webstore.sw.txt b/platform/mv3/description/webstore.sw.txt index ef089202b9565..946ebb9ed572c 100644 --- a/platform/mv3/description/webstore.sw.txt +++ b/platform/mv3/description/webstore.sw.txt @@ -1,12 +1,12 @@ -uBO Lite (uBOL) is an MV3-based content blocker. +uBO Lite (uBOL) ni kizuizi cha maudhui chenye msingi wa MV3. -The default ruleset corresponds to uBlock Origin's default filterset: +Seti chaguo-msingi ya sheria inalingana na seti chaguo-msingi ya vichujio ya uBlock Origin: -- uBlock Origin's built-in filter lists +- Orodha za vichujio zilizojengwa ndani ya uBlock Origin - EasyList - EasyPrivacy -- Peter Lowe’s Ad and tracking server list +- Orodha ya seva za matangazo na ufuatiliaji ya Peter Lowe -You can enable more rulesets by visiting the options page -- click the _Cogs_ icon in the popup panel. +Unaweza kuwezesha seti za sheria zaidi kwa kutembelea ukurasa wa chaguo -- bonyeza aikoni ya _Gia_ kwenye paneli inayoibuka. -uBOL is entirely declarative, meaning there is no need for a permanent uBOL process for the filtering to occur, and CSS/JS injection-based content filtering is performed reliably by the browser itself rather than by the extension. This means that uBOL itself does not consume CPU/memory resources while content blocking is ongoing -- uBOL's service worker process is required _only_ when you interact with the popup panel or the option pages. +uBOL ni ya kutangaza kabisa, ikimaanisha hakuna haja ya mchakato wa kudumu wa uBOL kwa uchujaji kutokea, na uchujaji wa maudhui unaotegemea kuingiza CSS/JS unafanywa kwa uaminifu na kivinjari chenyewe badala ya kiendelezi. Hii inamaanisha kuwa uBOL yenyewe haitumii rasilimali za CPU/kumbukumbu wakati uzuiaji wa maudhui unaendelea -- mchakato wa mfanyakazi wa huduma wa uBOL unahitajika _tu_ wakati unapoingiliana na paneli inayoibuka au kurasa za chaguo. diff --git a/platform/mv3/description/webstore.ta.txt b/platform/mv3/description/webstore.ta.txt index ef089202b9565..7d0f3c4a165e9 100644 --- a/platform/mv3/description/webstore.ta.txt +++ b/platform/mv3/description/webstore.ta.txt @@ -1,12 +1,12 @@ -uBO Lite (uBOL) is an MV3-based content blocker. +uBO Lite (uBOL) என்பது MV3 அடிப்படையிலான உள்ளடக்கத் தடுப்பான் ஆகும். -The default ruleset corresponds to uBlock Origin's default filterset: +இயல்புநிலை விதித் தொகுப்பு uBlock Origin இன் இயல்புநிலை வடிப்பான் தொகுப்புடன் ஒத்துள்ளது: -- uBlock Origin's built-in filter lists +- uBlock Origin இன் உள்ளமைக்கப்பட்ட வடிப்பான் பட்டியல்கள் - EasyList - EasyPrivacy -- Peter Lowe’s Ad and tracking server list +- பீட்டர் லோவின் விளம்பர மற்றும் கண்காணிப்பு சேவையகப் பட்டியல் -You can enable more rulesets by visiting the options page -- click the _Cogs_ icon in the popup panel. +விருப்பங்கள் பக்கத்தைப் பார்வையிடுவதன் மூலம் கூடுதல் விதித் தொகுப்புகளை இயக்கலாம் -- பாப்அப் பேனலில் உள்ள _கியர்கள்_ ஐகானைக் கிளிக் செய்யவும். -uBOL is entirely declarative, meaning there is no need for a permanent uBOL process for the filtering to occur, and CSS/JS injection-based content filtering is performed reliably by the browser itself rather than by the extension. This means that uBOL itself does not consume CPU/memory resources while content blocking is ongoing -- uBOL's service worker process is required _only_ when you interact with the popup panel or the option pages. +uBOL முற்றிலும் அறிவிப்பு முறையில் (declarative) உள்ளது, அதாவது வடிகட்டல் நடைபெற நிரந்தர uBOL செயல்முறை தேவையில்லை, மேலும் CSS/JS ஊசி அடிப்படையிலான உள்ளடக்க வடிகட்டல் நீட்டிப்பால் அல்லாமல் உலாவியாலேயே நம்பகத்தன்மையுடன் செய்யப்படுகிறது. இதன் பொருள், உள்ளடக்க தடுப்பு நடைபெற்றுக்கொண்டிருக்கும்போது uBOL தானே CPU/நினைவக வளங்களைப் பயன்படுத்துவதில்லை -- uBOL இன் சேவைப் பணியாளர் (service worker) செயல்முறை, நீங்கள் பாப்அப் பேனல் அல்லது விருப்பங்கள் பக்கங்களுடன் தொடர்பு கொள்ளும்போது _மட்டுமே_ தேவைப்படுகிறது. diff --git a/platform/mv3/description/webstore.te.txt b/platform/mv3/description/webstore.te.txt index ef089202b9565..8646fb149c139 100644 --- a/platform/mv3/description/webstore.te.txt +++ b/platform/mv3/description/webstore.te.txt @@ -1,12 +1,12 @@ -uBO Lite (uBOL) is an MV3-based content blocker. +uBO Lite (uBOL) అనేది MV3-ఆధారిత కంటెంట్ బ్లాకర్. -The default ruleset corresponds to uBlock Origin's default filterset: +డిఫాల్ట్ రూల్‌సెట్ uBlock Origin యొక్క డిఫాల్ట్ ఫిల్టర్‌సెట్‌కు అనుగుణంగా ఉంటుంది: -- uBlock Origin's built-in filter lists +- uBlock Origin యొక్క అంతర్నిర్మిత ఫిల్టర్ జాబితాలు - EasyList - EasyPrivacy -- Peter Lowe’s Ad and tracking server list +- Peter Lowe యొక్క ప్రకటన మరియు ట్రాకింగ్ సర్వర్ జాబితా -You can enable more rulesets by visiting the options page -- click the _Cogs_ icon in the popup panel. +మీరు ఎంపికల పేజీని సందర్శించడం ద్వారా మరిన్ని రూల్‌సెట్‌లను ప్రారంభించవచ్చు -- పాపప్ ప్యానెల్‌లోని _Cogs_ చిహ్నంపై క్లిక్ చేయండి. -uBOL is entirely declarative, meaning there is no need for a permanent uBOL process for the filtering to occur, and CSS/JS injection-based content filtering is performed reliably by the browser itself rather than by the extension. This means that uBOL itself does not consume CPU/memory resources while content blocking is ongoing -- uBOL's service worker process is required _only_ when you interact with the popup panel or the option pages. +uBOL పూర్తిగా డిక్లరేటివ్, అంటే ఫిల్టరింగ్ జరగడానికి శాశ్వత uBOL ప్రక్రియ అవసరం లేదు, మరియు CSS/JS ఇంజెక్షన్-ఆధారిత కంటెంట్ ఫిల్టరింగ్ ఎక్స్‌టెన్షన్ ద్వారా కాకుండా బ్రౌజర్ ద్వారా నమ్మదగిన రీతిలో నిర్వహించబడుతుంది. దీని అర్థం కంటెంట్ బ్లాకింగ్ జరుగుతున్నప్పుడు uBOL స్వయంగా CPU/మెమరీ వనరులను వినియోగించదు -- uBOL యొక్క సర్వీస్ వర్కర్ ప్రక్రియ _మీరు_ పాపప్ ప్యానెల్ లేదా ఎంపికల పేజీలతో సంకర్షణ చెందినప్పుడు మాత్రమే అవసరం. diff --git a/platform/mv3/description/webstore.ur.txt b/platform/mv3/description/webstore.ur.txt index 2d08caf5c88f9..590805088aeb1 100644 --- a/platform/mv3/description/webstore.ur.txt +++ b/platform/mv3/description/webstore.ur.txt @@ -1,4 +1,4 @@ -uBO Lite (uBOL) is an MV3-based content blocker. +uBO Lite (uBOL) ایک MV3 پر مبنی مواد بلاکر ہے۔ ڈیفالٹ رولسیٹ uBlock Origin کے ڈیفالٹ فلٹر سیٹ سے مساوی ہے: @@ -7,6 +7,6 @@ uBO Lite (uBOL) is an MV3-based content blocker. - EasyPrivacy - Peter Lowe’s Ad and tracking server list -You can enable more rulesets by visiting the options page -- click the _Cogs_ icon in the popup panel. +آپ آپشنز پیج پر جا کر مزید رول سیٹس کو فعال کر سکتے ہیں -- پاپ اپ پینل میں _Cogs_ آئیکن پر کلک کریں۔ -uBOL is entirely declarative, meaning there is no need for a permanent uBOL process for the filtering to occur, and CSS/JS injection-based content filtering is performed reliably by the browser itself rather than by the extension. This means that uBOL itself does not consume CPU/memory resources while content blocking is ongoing -- uBOL's service worker process is required _only_ when you interact with the popup panel or the option pages. +uBOL مکمل طور پر اعلانیہ ہے، مطلب یہ کہ فلٹرنگ کے لیے مستقل uBOL عمل کی ضرورت نہیں ہے، اور CSS/JS انجیکشن پر مبنی مواد کی فلٹرنگ توسیع کے بجائے براؤزر کے ذریعہ خود قابل اعتماد طریقے سے انجام دی جاتی ہے۔ اس کا مطلب ہے کہ مواد کی بلاکنگ جاری رہنے کے دوران uBOL خود CPU/میموری کے وسائل استعمال نہیں کرتا ہے -- uBOL کا سروس ورکر عمل _صرف_ اس وقت درکار ہوتا ہے جب آپ پاپ اپ پینل یا آپشنز پیجز کے ساتھ تعامل کرتے ہیں۔ diff --git a/platform/mv3/extension/_locales/ar/messages.json b/platform/mv3/extension/_locales/ar/messages.json index d8ff28acdd5b5..db206afd900ba 100644 --- a/platform/mv3/extension/_locales/ar/messages.json +++ b/platform/mv3/extension/_locales/ar/messages.json @@ -4,15 +4,15 @@ "description": "extension name." }, "extShortDesc": { - "message": "أداة فعالة لحجب المحتوى. تحجب الإعلانات والمتتبعين والمعدنين وغير ذلك فور تثبيتها.", + "message": "أداة فعالة لحجب المحتوى. يحجب الإعلانات، وأدوات التتبع، وبرمجيات التعدين، والمزيد فور التثبيت مباشرة.", "description": "this will be in the Chrome web store: must be 132 characters or less" }, "perRulesetStats": { - "message": "{{ruleCount}} قواعد، محولة من {{filterCount}} فلاتر الشبكة", + "message": "{{ruleCount}} من القواعد، تم تحويلها من {{filterCount}} من خيارات تصفية الشبكة", "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "dashboardName": { - "message": "لوحة التحكم", + "message": "uBO Lite — لوحة التحكم", "description": "English: uBO Lite — Dashboard" }, "settingsPageName": { @@ -20,7 +20,7 @@ "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "فلاتر مخصصة", + "message": "خيارات تصفية مخصصة", "description": "appears as tab name in dashboard" }, "developPageName": { @@ -35,16 +35,20 @@ "message": "سياسة الخصوصية", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "التوثيق", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "وضع التصفية", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "على هذا الموقع", + "message": "في هذا الموقع", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "الإبلاغ عن مشكلة في هذا الموقع", + "message": "الإبلاغ عن مشكلة", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { @@ -76,7 +80,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { - "message": "مضايقات", + "message": "عناصر إزعاج", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMisc": { @@ -87,14 +91,34 @@ "message": "المناطق واللغات", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "القوائم المستوردة", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "إضافة قائمة تصفية…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "رابط قائمة التصفية المراد إضافتها", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "لتطبيق مرشحات التجميل أو النصوص البرمجية الصغيرة من القوائم المستوردة، يجب منح uBO Lite إذنا لتشغيل نصوص المستخدم.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "استيراد / تصدير", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "الصق هنا فلاتر تجميلية محددة لإضافتها", + "message": "خيارات تصفية مظهر/سكريبت محددة لإضافتها", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "افتح صفحة الإضافات في متصفحك (chrome://extensions في Chrome أو about:addons في Firefox)، ثم افتح تفاصيل uBO Lite، وفعل خيار السماح بنصوص المستخدم (المعروف أيضا بـ \"نصوص الطرف الثالث غير الموثقة\").", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "سجل التغييرات", "description": "" @@ -116,7 +140,7 @@ "description": "Link text to translations repo" }, "aboutFilterLists": { - "message": "قوائم الفلاتر", + "message": "قوائم خيارات التصفية", "description": "Link text to uBO's own filter lists repo" }, "aboutDependencies": { @@ -128,19 +152,19 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { - "message": "الإبلاغ عن مشكلات التصفية الخاصة بمواقع الويب المحددة إلىuBlockOrigin/uAssetsمتتبع المشكلةيتطلب حساب GitHub", + "message": "الإبلاغ عن مشكلات خيارات التصفية المتعلقة بمواقع ويب محددة إلى uBlockOrigin/uAssets نظام تتبع المشكلات. يتطلب ذلك حسابا على GitHub.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { - "message": "معلومات استكشاف وإصلاح الأخطاء", + "message": "معلومات استكشاف الأخطاء وإصلاحها", "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "لتجنب تحميل المتطوعين بتقارير مكررة، يرجى التأكد من أن المشكلة لم يتم الإبلاغ عنها بالفعل. ملحوظة: النقر على الزر سيؤدي إلى إرسال أصل الصفحة إلى موقع GitHub.", + "message": "لتجنب إنهاك المتطوعين بتقارير مكررة، يرجى التأكد من أن المشكلة لم يتم الإبلاغ عنها من قبل.ملاحظة: النقر على الزر سيؤدي إلى إرسال أصل الصفحة إلى موقع GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "العثور على تقارير مماثلة", + "message": "العثور على تقارير مماثلة على GitHub", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { @@ -152,15 +176,15 @@ "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "— اختر إدخالًا —", + "message": "— اختر إدخالا —", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "يظهر الإعلانات أو بقايا الإعلانات", + "message": "يعرض إعلانات أو بقايا إعلانات", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "يحتوي على تراكبات أو إزعاجات أخرى", + "message": "يحتوي على طبقات تداخل أو عوائق أخرى", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { @@ -172,7 +196,7 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "تعطل عند تفعيل uBO Lite", + "message": "يحدث خلل وظيفي عندما يكون uBO Lite مفعلا", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { @@ -180,7 +204,7 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "يؤدي إلى برامج ضارة وتصيد احتيالي", + "message": "يؤدي إلى البرمجيات الضارة والاحتيال", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { @@ -208,11 +232,11 @@ "description": "Name of blocking mode 1" }, "filteringMode2Name": { - "message": "الأفضل", + "message": "الأمثل", "description": "Name of blocking mode 2" }, "filteringMode3Name": { - "message": "مكتمل", + "message": "كامل", "description": "Name of blocking mode 3" }, "basicFilteringModeDescription": { @@ -248,13 +272,29 @@ "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "تمكين الحظر الصارم", + "message": "تفعيل الحجب الصارم", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { "message": "سيتم حظر الانتقال إلى المواقع غير المرغوب فيها، وسيُعرض عليك خيار المتابعة.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "تفعيل حظر النوافذ المنبثقة", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "عند التفعيل، ستقوم المرشحات المطابقة تلقائيا بإغلاق علامات التبويب غير المرغوب فيها التي تنشئها المواقع.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "بيئة معزولة لإنشاء خيارات التصفية", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "لتطبيق مرشحات التجميل أو النصوص البرمجية الصغيرة من بيئة الاختبار، يجب منح uBO Lite إذنا لتشغيل نصوص المستخدم.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "وضع المطور", "description": "Label for a checkbox in the options page" @@ -276,7 +316,7 @@ "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "البحث عن القوائم", + "message": "البحث عن قوائم", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { @@ -288,7 +328,7 @@ "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "تم حظر الصفحة بسبب وجود فلتر مطابق في {{listname}}.", + "message": "تم حجب الصفحة بسبب خيار تصفية مطابق في{{listname}}.", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { @@ -308,7 +348,7 @@ "description": "A button to close the current tab" }, "strictblockDontWarn": { - "message": "لا تحذرني مرة أخرى من هذا الموقع", + "message": "لا تحذرني مجددا بشأن هذا الموقع", "description": "Label for checkbox in document-blocked page" }, "strictblockProceed": { @@ -324,11 +364,11 @@ "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "أنشئ تصفية مخصّصة", + "message": "إنشاء خيار تصفية مخصص", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "أزِل التصفية المخصّصة", + "message": "إزالة خيار تصفية مخصص", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { @@ -348,11 +388,11 @@ "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "مجموعة قواعد متغيرة", + "message": "مجموعة قواعد ديناميكية", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "مجموعة قواعد جَلسة", + "message": "مجموعة قواعد الجلسة", "description": "An option in a dropdown list" }, "saveButton": { @@ -360,11 +400,11 @@ "description": "Text for buttons used to save changes" }, "revertButton": { - "message": "إرجاع", + "message": "تراجع", "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "أضِف", + "message": "أضف", "description": "Text for buttons used to add content" }, "importAndAppendButton": { @@ -416,7 +456,7 @@ "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "اختر تصفية أدناه لتمييز العناصر المطابقة في صفحة الويب. انقر على سلة المهملات لإزالة التصفية.", + "message": "اختر خيار تصفية أدناه لتمييز العناصر المطابقة في صفحة الويب.\n انقر على سلة المهملات لإزالة خيار التصفية.", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/az/messages.json b/platform/mv3/extension/_locales/az/messages.json index c2a36cb32b508..8162b8d3fc088 100644 --- a/platform/mv3/extension/_locales/az/messages.json +++ b/platform/mv3/extension/_locales/az/messages.json @@ -8,7 +8,7 @@ "description": "this will be in the Chrome web store: must be 132 characters or less" }, "perRulesetStats": { - "message": "{{ruleCount}} rules, converted from {{filterCount}} network filters", + "message": "{{filterCount}} şəbəkə filtrindən {{ruleCount}} qayda çevrildi", "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "dashboardName": { @@ -20,11 +20,11 @@ "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "Custom filters", + "message": "Fərdi filtrlər", "description": "appears as tab name in dashboard" }, "developPageName": { - "message": "Develop", + "message": "İnkişaf etdir", "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { @@ -35,16 +35,20 @@ "message": "Məxfilik siyasəti", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Sənədləşmə", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { - "message": "filtering mode", + "message": "filtrləmə rejimi", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "On this website", + "message": "Bu veb-saytda", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "Report an issue", + "message": "Problemi bildirin", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Malware protection, security", + "message": "Zərərli proqram təminatından qorunma, təhlükəsizlik", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,14 +91,34 @@ "message": "Bölgələr, dillər", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "İdxal edilmiş siyahılar", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Filtr siyahısı əlavə et…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Əlavə ediləcək filtr siyahısının URL-i", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "İdxal olunmuş siyahılardan kosmetik və ya skriptlet filtrlərini tətbiq etmək üçün uBO Lite-a istifadəçi skriptlərini icra etmək icazəsi verəsiniz.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { - "message": "Import / Export", + "message": "İdxal / İxrac et", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "Əlavə ediləcək xüsusi kosmetik/skriptlet filtrləri", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Brauzerinizin genişləndirmələr səhifəsini açın (Chrome-da chrome://extensions və ya Firefox-da about:addons), uBO Lite bölməsinin təfərrüatlarını açın və İstifadəçi skriptlərinə icazə ver seçimini aktivləşdirin (bu seçim “təsdiqlənməmiş üçüncü tərəf skriptləri” kimi də adlandırılır).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Dəyişikliklər siyahısı", "description": "" @@ -120,91 +144,91 @@ "description": "Link text to uBO's own filter lists repo" }, "aboutDependencies": { - "message": "External dependencies (GPLv3-compatible):", + "message": "Xarici asılılıqlar (GPLv3 ilə uyğundur):", "description": "Shown in the About pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "Filtrlə bağlı problemi bildirin", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "Müəyyən veb-saytlarla bağlı filtr problemlərini uBlockOrigin/uAssets problem izləyicisinə bildirin. GitHub hesabı tələb olunur.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting information", + "message": "Problemlərin aradan qaldırılması haqqında məlumat", "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "Könüllüləri təkrarlanan bildirişlərlə yükləməmək üçün problemin artıq bildirilmədiyini yoxlayın. Qeyd: düyməyə kliklədikdə səhifənin mənşəyi GitHub-a göndəriləcək.", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "GitHub-da oxşar bildirişləri tapın", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "Veb-səhifənin ünvanı:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "Veb-səhifə…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- Bir seçim edin --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "Reklamları və ya reklam qalıqlarını göstərir", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "Üst qatlara və ya digər narahatedici elementlərə malikdir", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBO Lite", + "message": "uBO Lite-ı aşkarlayır", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "Məxfiliklə bağlı problemlərə malikdir", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBO Lite is enabled", + "message": "uBO Lite aktiv olduqda düzgün işləmir", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "Arzuolunmaz vərəqələri və ya pəncərələri açır", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "Zərərli proqramlara və fişinqə yönləndirir", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "Veb-səhifəni “NSFW” (“İş üçün təhlükəsiz deyil”) kimi işarələ", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "GitHub-da yeni bildiriş yaradın", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { - "message": "Default filtering mode", + "message": "Standart filtr rejimi", "description": "The header text for the default filtering mode section" }, "defaultFilteringModeDescription": { - "message": "The default filtering mode will be overridden by per-website filtering modes. You can adjust the filtering mode on any given website according to whichever mode works best on that website. Each mode has its advantages and disadvantages.", + "message": "Standart filtr rejimi veb-sayt üzrə filtr rejimləri ilə əvəz olunacaq. İstənilən veb-saytda filtr rejimini həmin sayt üçün ən yaxşı işləyən rejimə uyğunlaşdıra bilərsiniz. Hər rejimin öz üstünlükləri və çatışmazlıqları var.", "description": "This describes the default filtering mode setting" }, "filteringMode0Name": { - "message": "no filtering", + "message": "filtrləmə yoxdur", "description": "Name of blocking mode 0" }, "filteringMode1Name": { - "message": "basic", + "message": "əsas", "description": "Name of blocking mode 1" }, "filteringMode2Name": { @@ -212,211 +236,227 @@ "description": "Name of blocking mode 2" }, "filteringMode3Name": { - "message": "complete", + "message": "tam", "description": "Name of blocking mode 3" }, "basicFilteringModeDescription": { - "message": "Basic network filtering from selected filter lists.\n\nDoes not require permission to read and modify data on websites.", + "message": "Seçilmiş filtr siyahılarından əsas şəbəkə filtrlənməsi.\n\nVeb-saytlardakı məlumatları oxumaq və dəyişdirmək üçün icazə tələb etmir.", "description": "This describes the 'basic' filtering mode" }, "optimalFilteringModeDescription": { - "message": "Advanced network filtering plus specific extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.", + "message": "Seçilmiş filtr siyahılarından genişləndirilmiş xüsusi filtrləmə ilə yanaşı, təkmil şəbəkə filtrlənməsi.\n\nBütün veb-saytlardakı məlumatları oxumaq və dəyişdirmək üçün geniş icazə tələb edir.", "description": "This describes the 'optimal' filtering mode" }, "completeFilteringModeDescription": { - "message": "Advanced network filtering plus specific and generic extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.\n\nGeneric extended filtering may cause higher web page resources usage.", + "message": "Seçilmiş filtr siyahılarından xüsusi və ümumi genişləndirilmiş filtrləmə ilə yanaşı, təkmil şəbəkə filtrlənməsi.\n\nBütün veb-saytlardakı məlumatları oxumaq və dəyişdirmək üçün geniş icazə tələb edir.\n\nÜmumi genişləndirilmiş filtrləmə veb-səhifə resurslarının daha çox istifadəsinə səbəb ola bilər.", "description": "This describes the 'complete' filtering mode" }, "noFilteringModeDescription": { - "message": "List of websites for which no filtering will take place.", + "message": "Filtrləmənin aparılmayacağı veb-saytların siyahısı.", "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { - "message": "[hostnames only]\nexample.com\ngames.example\n...", + "message": "[yalnız host adları]\nexample.com\ngames.example\n...", "description": "Default text for in edit field" }, "behaviorSectionLabel": { - "message": "Behavior", + "message": "Davranış", "description": "The header text for the 'Behavior' section" }, "autoReloadLabel": { - "message": "Automatically reload page when changing filtering mode", + "message": "Filtr rejimi dəyişdirildikdə səhifəni avtomatik yenidən yüklə", "description": "Label for a checkbox in the options page" }, "showBlockedCountLabel": { - "message": "Show the number of blocked requests on the toolbar icon", + "message": "Bloklanmış sorğuların sayını alətlər paneli ikonunda göstər", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "Enable strict blocking", + "message": "Sərt bloklamanı aktivləşdir", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "Potensial olaraq arzuolunmaz saytlara keçid bloklanacaq və davam etmək seçimi sizə təqdim olunacaq.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Pop-up bloklamasını aktivləşdir", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Aktiv olduqda uyğun filtrlər veb-saytlar tərəfindən yaradılmış arzuolunmaz brauzer vərəqələrini avtomatik bağlayacaq.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Filtr yaratma sınaq mühiti", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "Sandbox-dan kosmetik və ya skriptlet filtrlərini tətbiq etmək üçün uBO Lite-a istifadəçi skriptlərini icra etmək icazəsi verəsiniz.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Developer mode", + "message": "Tərtibatçı rejimi", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "Texniki istifadəçilər üçün uyğun funksiyalara girişi aktivləşdirir.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "Nüsxələmə", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "Fərdi tənzimləmələrinizi bir fayla nüsxələyin, yaxud fayldan bərpa edin.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "Bərpa etmə bütün cari fərdi parametrlərinizin üzərinə yazacaq.", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "Find lists", + "message": "Siyahıları tap", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { - "message": "Page blocked", + "message": "Səhifə əngəlləndi", "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite has prevented the following page from loading:", + "message": "uBO Lite aşağıdakı səhifənin yüklənməsinin qarşısını aldı:", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "The page was blocked because of a matching filter in {{listname}}.", + "message": "Səhifə {{listname}} siyahısındakı uyğun filtrə görə bloklandı.", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "Bloklanmış səhifə başqa sayta yönləndirmək istəyir. Davam etməyi seçsəniz, birbaşa bu ünvana keçəcəksiniz:", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { - "message": "without parameters", + "message": "parametrlərsiz", "description": "Label to be used for the parameter-less URL" }, "strictblockBack": { - "message": "Go back", + "message": "Geriyə qayıt", "description": "A button to go back to the previous web page" }, "strictblockClose": { - "message": "Close this window", + "message": "Bu pəncərəni bağla", "description": "A button to close the current tab" }, "strictblockDontWarn": { - "message": "Don't warn me again about this site", + "message": "Bu sayt barədə məni xəbərdar etmə", "description": "Label for checkbox in document-blocked page" }, "strictblockProceed": { - "message": "Proceed", + "message": "Davam et", "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Remove an element", + "message": "Elementi sil", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Exit element zapper mode", + "message": "Element silmə rejimindən çıx", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "Fərdi filtr yarat", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "Fərdi filtri sil", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { - "message": "View:", + "message": "Görünüş:", "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "Filtr rejiminin təfərrüatları", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "Fərdi DNR qaydaları", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "… üçün DNR qaydaları", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "Dinamik qaydalar dəsti", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "Sessiya qaydalar dəsti", "description": "An option in a dropdown list" }, "saveButton": { - "message": "Save", + "message": "Saxla", "description": "Text for buttons used to save changes" }, "revertButton": { - "message": "Revert", + "message": "Qaytar", "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "Add", + "message": "Əlavə et", "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Import and append…", + "message": "İdxal və əlavə et…", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Export…", + "message": "İxrac et…", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "Nüsxələ…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "Bərpa et…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "Standart tənzimləmələrə sıfırla…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "Bütün fərdi tənzimləmələriniz silinəcək. Həqiqətən standart tənzimləmələrə sıfırlamaq istəyirsiniz?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "Etibarsız mənbələrdən məzmun əlavə etməyin", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "Qeydə alınmış qayda sayı: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "Ən yaxşı uyğunluğu seçmək üçün sürüşdürücünü tərpədin", "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Pick", + "message": "Seç", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "Önbaxış", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "Yarat", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "Vebsəhifədə uyğun gələn elementləri vurğulamaq üçün aşağıdan bir filtr seçin. Filtri silmək üçün çöp qutusuna klikləyin.", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/be/messages.json b/platform/mv3/extension/_locales/be/messages.json index b722c0f0233a0..b5158de374f2d 100644 --- a/platform/mv3/extension/_locales/be/messages.json +++ b/platform/mv3/extension/_locales/be/messages.json @@ -35,6 +35,10 @@ "message": "Палітыка прыватнасці", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Дакументацыя", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "рэжым фільтравання", "description": "Label in the popup panel for the current filtering mode" @@ -44,7 +48,7 @@ "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "Паведаміць пра праблему на гэтым вэб-сайце", + "message": "Паведаміць пра праблему", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Дамены шкодных праграм", + "message": "Абарона ад шкоднасных праграм, бяспека", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,14 +91,34 @@ "message": "Рэгіёны, мовы", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Імпартаваныя спісы", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Дадаць спіс фільтраў…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Устаўце сюды URL-адрас спіса фільтраў, які трэба дадаць", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Імпартаваць/экспартаваць", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Устаўце сюды спецыяльныя касметычныя фільтры для дадання", + "message": "Устаўце сюды спецыяльныя касметычныя фільтры, якія трэба дадаць", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Адкрыйце старонку пашырэнняў вашага браўзера (chrome://extensions у Chrome або about:addons у Firefox), адкрыйце падрабязнасці uBO Lite і ўключыце Дазволіць карыстальніцкія скрыпты (таксама вядомыя як «неправераныя староннія скрыпты»).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Журнал змяненняў", "description": "" @@ -136,11 +160,11 @@ "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "Каб не абцяжарваць добраахвотнікаў дубляванымі справаздачамі, калі ласка, пераканайцеся, што пра гэтую праблему не паведамлялі раней.", + "message": "Каб не абцяжарваць добраахвотнікаў дубляванымі справаздачамі, праверце, ці не паведамлялі пра гэтую праблему раней. Заўвага: націсканне кнопкі прывядзе да адпраўкі паходжання старонкі на GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Знайсці падобныя справаздачы", + "message": "Знайсці падобныя справаздачы на GitHub", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { @@ -188,7 +212,7 @@ "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Стварыць новую справаздачу", + "message": "Стварыць новую справаздачу на GitHub", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { @@ -255,8 +279,24 @@ "message": "Пераход да патэнцыйна непажаданых сайтаў будзе заблакаваны, і вам будзе прапанавана магчымасць працягнуць.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Уключыць блакаванне ўсплывальных вокнаў", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Калі актыўна, адпаведныя фільтры будуць аўтаматычна закрываць непажаданыя карткі браўзера, створаныя вэб-сайтамі.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Пясочніца стварэння фільтраў", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Рэжым распрацоўніка", + "message": "Рэжым распрацоўшчыка", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { @@ -316,7 +356,7 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Перайсці ў рэжым імгненнага хавання элементаў", + "message": "Выдаліць элемент", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { @@ -344,7 +384,7 @@ "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "Правілы у DNR", + "message": "Правілы у DNR …", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { @@ -384,11 +424,11 @@ "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Скід да налад па змаўчанні…", + "message": "Скінуць да прадвызначаных налад…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "Усе вашыя прыстасаваныя наладкі будуць выдалены. Вы сапраўды хочаце вярнуцца да налад па змаўчанні?", + "message": "Усе карыстальніцкія налады будуць выдалены. Вы сапраўды хочаце скінуць налады да прадвызначаных?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { diff --git a/platform/mv3/extension/_locales/bg/messages.json b/platform/mv3/extension/_locales/bg/messages.json index 3a216e0a30ec2..b5a5940cd29ca 100644 --- a/platform/mv3/extension/_locales/bg/messages.json +++ b/platform/mv3/extension/_locales/bg/messages.json @@ -35,6 +35,10 @@ "message": "Политика за поверителност", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Документация", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "режим на филтриране", "description": "Label in the popup panel for the current filtering mode" @@ -87,6 +91,22 @@ "message": "Региони, езици", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Импортирани списъци", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Добавяне на списък с филтри…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Поставете тук URL адреса на списъка с филтри, който искате да добавите", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "За да приложите козметични филтри или скриптови филтри от импортирани списъци, трябва да предоставите на uBO Lite разрешение за изпълнение на потребителски скриптове.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Импортиране / експортиране", "description": "Text label heading the import/export area of custom filters" @@ -95,6 +115,10 @@ "message": "Поставете тук конкретни козметични филтри, които искате да добавите", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Отворете страницата с разширенията на браузъра си (chrome://extensions в Chrome или about:addons във Firefox), отворете подробностите за uBO Lite и активирайте опцията Разрешаване на потребителски скриптове (наричани още „непроверени скриптове от трети страни“).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Списък с промени", "description": "" @@ -255,6 +279,22 @@ "message": "Навигацията към потенциално нежелани сайтове ще бъде блокирана и ще ви бъде предложена възможността да продължите.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Активиране на блокирането на изскачащи прозорци", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Когато тази функция е активирана, филтрите за съвпадение автоматично затварят нежеланите раздели в браузъра, създадени от уебсайтове.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Тестова среда за създаване на филтри", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "За да активирате козметични филтри или скриптлет филтри от пясъчника, трябва да предоставите на uBO Lite разрешение за изпълнение на потребителски скриптове.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Режим за програмисти", "description": "Label for a checkbox in the options page" @@ -316,7 +356,7 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Влизане в режима на временно скриване на елемента", + "message": "Премахване на елемент", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { @@ -344,7 +384,7 @@ "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "Правила на DNR за ...", + "message": "Правила на DNR за …", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { diff --git a/platform/mv3/extension/_locales/bn/messages.json b/platform/mv3/extension/_locales/bn/messages.json index 187d12dae7d6e..31a53f76ca443 100644 --- a/platform/mv3/extension/_locales/bn/messages.json +++ b/platform/mv3/extension/_locales/bn/messages.json @@ -20,11 +20,11 @@ "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "Custom filters", + "message": "কাস্টম ফিল্টার", "description": "appears as tab name in dashboard" }, "developPageName": { - "message": "Develop", + "message": "ডেভেলপ", "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { @@ -35,12 +35,16 @@ "message": "গোপনীয়তার নীতিমালা", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "ডকুমেন্টেশন", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "ফিল্টারিং মোড", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "On this website", + "message": "এই ওয়েবসাইটে", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { @@ -87,14 +91,34 @@ "message": "অঞ্চল, ভাষা", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "আমদানিকৃত তালিকা", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "ফিল্টার তালিকা যোগ করুন…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "যোগ করার জন্য ফিল্টার তালিকার URL", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { - "message": "Import / Export", + "message": "আমদানি / রপ্তানি", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "যোগ করার জন্য নির্দিষ্ট কসমেটিক/স্ক্রিপ্টলেট ফিল্টার", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "আপনার ব্রাউজারের এক্সটেনশন পৃষ্ঠা খুলুন (Chrome-এ chrome://extensions অথবা Firefox-এ about:addons), uBO Lite-এর বিস্তারিত খুলুন, এবং Allow user scripts (যা \"অযাচাইকৃত তৃতীয়-পক্ষ স্ক্রিপ্ট\" নামেও পরিচিত) চালু করুন।", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "পরিবর্তনসূচি", "description": "" @@ -255,6 +279,22 @@ "message": "সম্ভাব্য অযাচিত ওয়েবসাইট অবরুদ্ধ করা হবে, আর সেখানে আগানোর উপায় দেওয়া থাকবে।", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "পপ-আপ ব্লকিং সক্রিয় করুন", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "সক্রিয় থাকলে, মিলে যাওয়া ফিল্টারগুলি ওয়েবসাইট দ্বারা তৈরি অবাঞ্ছিত ব্রাউজার ট্যাবগুলি স্বয়ংক্রিয়ভাবে বন্ধ করে দেবে।", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "ফিল্টার তৈরির স্যান্ডবক্স", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "ডেভেলপার মোড", "description": "Label for a checkbox in the options page" @@ -264,15 +304,15 @@ "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "ব্যাকআপ", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "আপনার কাস্টম সেটিংস একটি ফাইলে ব্যাক আপ করুন, অথবা একটি ফাইল থেকে আপনার কাস্টম সেটিংস পুনরুদ্ধার করুন।", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "পুনরুদ্ধার করলে আপনার বর্তমান সকল কাস্টম সেটিংস ওভাররাইট হবে।", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { @@ -316,43 +356,43 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "এলিমেন্ট জ্যাপার মোডে প্রবেশ করুন", + "message": "একটি উপাদান সরান", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Exit element zapper mode", + "message": "এলিমেন্ট জ্যাপার মোড থেকে প্রস্থান করুন", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "একটি কাস্টম ফিল্টার তৈরি করুন", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "একটি কাস্টম ফিল্টার সরান", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { - "message": "View:", + "message": "দেখুন:", "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "ফিল্টারিং মোডের বিবরণ", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "কাস্টম DNR নিয়ম", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "... এর DNR নিয়ম", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "ডায়নামিক রুলসেট", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "সেশন রুলসেট", "description": "An option in a dropdown list" }, "saveButton": { @@ -360,63 +400,63 @@ "description": "Text for buttons used to save changes" }, "revertButton": { - "message": "Revert", + "message": "পূর্বাবস্থায় ফেরান", "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "Add", + "message": "যোগ করুন", "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Import and append…", + "message": "আমদানি ও সংযোজন…", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Export…", + "message": "রপ্তানি…", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "ব্যাক আপ…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "পুনরুদ্ধার…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "ডিফল্ট সেটিংসে রিসেট…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "আপনার সকল কাস্টম সেটিংস মুছে ফেলা হবে। আপনি কি সত্যিই ডিফল্ট সেটিংসে রিসেট করতে চান?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "অবিশ্বস্ত উৎস থেকে কন্টেন্ট যোগ করবেন না", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "নিবন্ধিত নিয়মের সংখ্যা: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "সেরা মিলটি নির্বাচন করতে স্লাইডারটি সরান", "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Pick", + "message": "বাছাই করুন", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "প্রিভিউ", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "তৈরি করুন", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "ওয়েব পৃষ্ঠায় মিলে যাওয়া উপাদানগুলি হাইলাইট করতে নিচের একটি ফিল্টার নির্বাচন করুন। একটি ফিল্টার সরাতে ট্র্যাশ ক্যানে ক্লিক করুন।", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/br_FR/messages.json b/platform/mv3/extension/_locales/br_FR/messages.json index 19e8805164c5a..a5653fffd9f1e 100644 --- a/platform/mv3/extension/_locales/br_FR/messages.json +++ b/platform/mv3/extension/_locales/br_FR/messages.json @@ -35,6 +35,10 @@ "message": "Politikerezh ar vuhez prevez", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Teuliadur", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "mod silañ", "description": "Label in the popup panel for the current filtering mode" @@ -87,14 +91,34 @@ "message": "Rannvroioù, broioù", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Listennoù enporzhiet", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Ouzhpennañ ul listenn siloù…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Pegit amañ URL al listenn siloù a fell deoc'h ouzhpennañ", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Enporzhiañ / Ezporzhiañ", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Eilañ amañ ar siloù kenedel resis da ouzhpennañ", + "message": "Pegit amañ ar siloù kenedel/scriptlet resis da ouzhpennañ", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Open your browser's extensions page (chrome://extensions in Chrome or about:addons in Firefox), open uBO Lite details, and toggle on Allow user scripts (also referred to as “unverified third-party scripts”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Deizlevr ar cheñchamantoù", "description": "" @@ -255,6 +279,22 @@ "message": "Stanket e vo ar merdeiñ etrezek lec'hiennoù a c'hallfe bezañ dañjerus, ha moaien a vo deoc'h dibab da genderc'hel pe get.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Enaouiñ stankañ ar pop-upoù", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Pa vez gweredekaet, an ivinelloù dic'hoantaet krouet gant al lec'hiennoù a vo serret gant ar siloù.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Tachenn krouiñ siloù", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Mod diorroer", "description": "Label for a checkbox in the options page" @@ -268,7 +308,7 @@ "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "Gwaredit hoc'h arventennoù personelaet en ur restr pe adsavit hoc'h arventennoù personelaet adalek ur restr.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { @@ -316,7 +356,7 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Mont er mod \"dilemel elfennoù\"", + "message": "Dilemel un elfenn", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { diff --git a/platform/mv3/extension/_locales/bs/messages.json b/platform/mv3/extension/_locales/bs/messages.json index aded553891b52..18d30d264559c 100644 --- a/platform/mv3/extension/_locales/bs/messages.json +++ b/platform/mv3/extension/_locales/bs/messages.json @@ -35,6 +35,10 @@ "message": "Politika privatnosti", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Documentation", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "način filtriranja", "description": "Label in the popup panel for the current filtering mode" @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Zloćudne domene", + "message": "Zaštita od zlonamjernog softvera, sigurnost", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,6 +91,22 @@ "message": "Regije, jezici", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Imported lists", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Add filter list…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL of the filter list to add", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Uvezi / Izvezi", "description": "Text label heading the import/export area of custom filters" @@ -95,6 +115,10 @@ "message": "Ovdje zalijepite određene kozmetičke filtere koje želite dodati", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Open your browser's extensions page (chrome://extensions in Chrome or about:addons in Firefox), open uBO Lite details, and toggle on Allow user scripts (also referred to as “unverified third-party scripts”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Dnevnik izmjena", "description": "" @@ -255,6 +279,22 @@ "message": "Navigacija do potencijalno neželjenih stranica bit će blokirana i bit će vam ponuđena mogućnost da nastavite.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Enable pop-up blocking", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "When active, matching filters will automatically close unwanted browser tabs created by websites.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Filter-creation sandbox", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Režim za razvojne programere", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/ca/messages.json b/platform/mv3/extension/_locales/ca/messages.json index 4e22d26d8937f..13f0ff744e045 100644 --- a/platform/mv3/extension/_locales/ca/messages.json +++ b/platform/mv3/extension/_locales/ca/messages.json @@ -35,6 +35,10 @@ "message": "Política de privadesa", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Documentació", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "mode de filtre", "description": "Label in the popup panel for the current filtering mode" @@ -87,6 +91,22 @@ "message": "Regions, llengües", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Llistes importades", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Afegeix una llista de filtres…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Enganxeu aquí l'URL de la llista de filtres per a afegir-la", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "Per a aplicar filtres cosmètics o scripts a les llistes importades, doneu permís a l'uBO Lite d'execució de scripts d'usuari.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Importa/Exporta", "description": "Text label heading the import/export area of custom filters" @@ -95,6 +115,10 @@ "message": "Enganxeu aquí els filtres cosmètics que voleu afegir", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Obriu la pàgina d'extensions del navegador (chrome://extensions al Chrome o about:addons al Firefox), obriu els detalls d'uBO Lite i activeu Permet scripts d'usuari (també anomenats «scripts de tercers no verificats»).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Registre de canvis", "description": "" @@ -140,7 +164,7 @@ "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Cerca d'informes semblants", + "message": "Cerca informes similars al GitHub", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { @@ -188,7 +212,7 @@ "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Crea un informe nou", + "message": "Crea un informe nou al GitHub", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { @@ -255,6 +279,22 @@ "message": "Es blocarà la navegació en webs potencialment no desitjables, oferint-vos la possibilitat de continuar.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Activa el bloqueig de finestres emergents", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "En activar-se, els filtres coincidents tancaran automàticament les pestanyes del navegador no desitjades creades pels llocs web.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Entorn de proves per a la creació de filtres", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "Per a aplicar filtres cosmètics o scripts des de l'entorn de proves, doneu permís a l'uBO Lite d'execució de scripts d'usuari.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Mode de desenvolupador", "description": "Label for a checkbox in the options page" @@ -316,7 +356,7 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Accedeix al mode d'eliminació d'elements", + "message": "Elimina un element", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { diff --git a/platform/mv3/extension/_locales/cs/messages.json b/platform/mv3/extension/_locales/cs/messages.json index ebf8afd67a44b..e098d7bf97d34 100644 --- a/platform/mv3/extension/_locales/cs/messages.json +++ b/platform/mv3/extension/_locales/cs/messages.json @@ -35,6 +35,10 @@ "message": "Zásady ochrany osobních údajů", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Dokumentace", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "režim filtrování", "description": "Label in the popup panel for the current filtering mode" @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Malware domény", + "message": "Ochrana před malwarem, zabezpečení", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,14 +91,34 @@ "message": "Regionální, jazykové", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Importované seznamy", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Přidat seznam filtrů…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Sem vložte adresu URL seznamu filtrů, které chcete přidat", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "Chcete-li použít filtry vzhledu nebo skriptové filtry z importovaných seznamů, musíte uBO Lite udělit oprávnění ke spouštění uživatelských skriptů.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Import / Export", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Vložte sem konkrétní kosmetické filtry, které chcete přidat", + "message": "Sem vložte konkrétní kosmetické/scriplet filtry, které chcete přidat", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Otevřete stránku s rozšířeními ve svém prohlížeči (chrome://extensions v prohlížeči Chrome nebo about:addons v prohlížeči Firefox), otevřete podrobnosti o rozšíření uBO Lite a zapněte volbu Povolit uživatelské skripty (také označované jako \"neověřené skripty třetích stran\").", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Přehled změn", "description": "" @@ -148,7 +172,7 @@ "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "Webová stránka...", + "message": "Webová stránka…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { @@ -228,11 +252,11 @@ "description": "This describes the 'complete' filtering mode" }, "noFilteringModeDescription": { - "message": "Seznam názvů hostitelů, pro které nebude probíhat žádné filtrování.", + "message": "Seznam webových stránek, pro které nebude probíhat žádné filtrování.", "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { - "message": "[jen názvy hostitelů]\nexample.com\ngames.example\n...", + "message": "[jen názvy hostitelů]\nexample.com\ngames.example\n…", "description": "Default text for in edit field" }, "behaviorSectionLabel": { @@ -255,6 +279,22 @@ "message": "Bude zablokována navigace na potenciálně nežádoucí stránky a bude Vám nabídnuta volba pro pokračování.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Povolit blokování vyskakovacích oken", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Pokud jsou tyto filtry aktivní, automaticky zavírají nežádoucí karty prohlížeče otevřené webovými stránkami.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Testovací prostředí pro vytváření filtrů", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "Chcete-li v sandboxu aktivovat filtry vzhledu nebo skriptové filtry, musíte uBO Lite udělit oprávnění ke spouštění uživatelských skriptů.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Vývojářský režim", "description": "Label for a checkbox in the options page" @@ -344,7 +384,7 @@ "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "Pravidla DNR pro...", + "message": "Pravidla DNR pro…", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { @@ -368,23 +408,23 @@ "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Importovat a připojit...", + "message": "Importovat a připojit…", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Exportovat...", + "message": "Exportovat…", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Zálohovat...", + "message": "Zálohovat…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Obnovit...", + "message": "Obnovit…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Resetovat do výchozího nastavení...", + "message": "Resetovat do výchozího nastavení…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { diff --git a/platform/mv3/extension/_locales/cv/messages.json b/platform/mv3/extension/_locales/cv/messages.json index 881b780e38fa2..61c922e16d28c 100644 --- a/platform/mv3/extension/_locales/cv/messages.json +++ b/platform/mv3/extension/_locales/cv/messages.json @@ -35,6 +35,10 @@ "message": "Privacy policy", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Documentation", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "filtering mode", "description": "Label in the popup panel for the current filtering mode" @@ -87,14 +91,34 @@ "message": "Regions, languages", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Imported lists", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Add filter list…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL of the filter list to add", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Import / Export", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "Specific cosmetic/scriptlet filters to add", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Open your browser's extensions page (chrome://extensions in Chrome or about:addons in Firefox), open uBO Lite details, and toggle on Allow user scripts (also referred to as “unverified third-party scripts”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Changelog", "description": "" @@ -255,6 +279,22 @@ "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Enable pop-up blocking", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "When active, matching filters will automatically close unwanted browser tabs created by websites.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Filter-creation sandbox", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Developer mode", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/cy/messages.json b/platform/mv3/extension/_locales/cy/messages.json index 4eae9fa9a34fc..21ff1a448afa7 100644 --- a/platform/mv3/extension/_locales/cy/messages.json +++ b/platform/mv3/extension/_locales/cy/messages.json @@ -8,7 +8,7 @@ "description": "this will be in the Chrome web store: must be 132 characters or less" }, "perRulesetStats": { - "message": "{{ruleCount}} rules, converted from {{filterCount}} network filters", + "message": "{{ruleCount}} rheol, wedi'u trosi o {{filterCount}} hidl rhwydwaith", "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "dashboardName": { @@ -20,7 +20,7 @@ "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "Custom filters", + "message": "Hidlau arferol", "description": "appears as tab name in dashboard" }, "developPageName": { @@ -35,6 +35,10 @@ "message": "Polisi preifatrwydd", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Dogfennaeth", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "modd hidlo", "description": "Label in the popup panel for the current filtering mode" @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Malware protection, security", + "message": "Amddiffyniad rhag meddalwedd faleisus, diogelwch", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,14 +91,34 @@ "message": "Rhanbarthau, ieithoedd", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Rhestrau wedi'u mewnforio", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Ychwanegu rhestr hidl…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL y rhestr hidl i'w hychwanegu", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Mewnforio / Allforio", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "Hidlau cosmetig/sgriptlet penodol i'w hychwanegu", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Agorwch dudalen estyniadau eich porwr (chrome://extensions yn Chrome neu about:addons yn Firefox), agorwch fanylion uBO Lite, a throwch Caniatáu sgriptiau defnyddiwr ymlaen (a elwir hefyd yn “sgriptiau trydydd parti heb eu gwirio”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Cofnod newidiadau", "description": "" @@ -128,15 +152,15 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "Adroddwch am broblemau hidlo gyda gwefannau penodol i uBlockOrigin/uAssets olrheiniwr materion. Mae angen cyfrif GitHub.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting information", + "message": "Gwybodaeth datrys problemau", "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "Er mwyn osgoi baich ar wirfoddolwyr gydag adroddiadau dyblyg, gwiriwch nad yw'r mater eisoes wedi'i adrodd. Nodyn: bydd clicio'r botwm yn achosi i darddiad y dudalen gael ei anfon i GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { @@ -152,51 +176,51 @@ "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- Dewiswch gofnod --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "Yn dangos hysbysebion neu weddillion hysbysebion", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "Mae gorgysylltiadau neu niwsansau eraill", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBO Lite", + "message": "Yn canfod uBO Lite", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "Mae materion sy'n ymwneud â phreifatrwydd", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBO Lite is enabled", + "message": "Yn camweithio pan fydd uBO Lite wedi'i alluogi", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "Yn agor tabiau neu ffenestri diangen", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "Yn arwain at feddalwedd faleisus, gwe-rwydo", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "Labelu'r dudalen we fel “NSFW” (“Ddim yn Ddiogel ar gyfer Gwaith”)", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "Creu adroddiad newydd ar GitHub", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { - "message": "Default filtering mode", + "message": "Modd hidlo diofyn", "description": "The header text for the default filtering mode section" }, "defaultFilteringModeDescription": { - "message": "The default filtering mode will be overridden by per-website filtering modes. You can adjust the filtering mode on any given website according to whichever mode works best on that website. Each mode has its advantages and disadvantages.", + "message": "Bydd moddau hidlo fesul gwefan yn gor-reoli'r modd hidlo diofyn. Gallwch addasu'r modd hidlo ar unrhyw wefan benodol yn unol â'r modd sy'n gweithio orau ar y wefan honno. Mae gan bob modd ei fanteision a'i anfanteision.", "description": "This describes the default filtering mode setting" }, "filteringMode0Name": { @@ -216,23 +240,23 @@ "description": "Name of blocking mode 3" }, "basicFilteringModeDescription": { - "message": "Basic network filtering from selected filter lists.\n\nDoes not require permission to read and modify data on websites.", + "message": "Hidlo rhwydwaith sylfaenol o restrau hidl a ddewiswyd.\n\nNid oes angen caniatâd i ddarllen ac addasu data ar wefannau.", "description": "This describes the 'basic' filtering mode" }, "optimalFilteringModeDescription": { - "message": "Advanced network filtering plus specific extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.", + "message": "Hidlo rhwydwaith uwch yn ogystal â hidlo estynedig penodol o restrau hidl a ddewiswyd.\n\nMae angen caniatâd eang i ddarllen ac addasu data ar bob gwefan.", "description": "This describes the 'optimal' filtering mode" }, "completeFilteringModeDescription": { - "message": "Advanced network filtering plus specific and generic extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.\n\nGeneric extended filtering may cause higher web page resources usage.", + "message": "Hidlo rhwydwaith uwch yn ogystal â hidlo estynedig penodol a generig o restrau hidl a ddewiswyd.\n\nMae angen caniatâd eang i ddarllen ac addasu data ar bob gwefan.\n\nGall hidlo estynedig generig achosi defnydd uwch o adnoddau tudalen we.", "description": "This describes the 'complete' filtering mode" }, "noFilteringModeDescription": { - "message": "List of websites for which no filtering will take place.", + "message": "Rhestr o wefannau na fydd unrhyw hidlo yn digwydd ar eu cyfer.", "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { - "message": "[hostnames only]\nexample.com\ngames.example\n...", + "message": "[enwau gwesteiwyr yn unig]\nexample.com\ngames.example\n...", "description": "Default text for in edit field" }, "behaviorSectionLabel": { @@ -244,39 +268,55 @@ "description": "Label for a checkbox in the options page" }, "showBlockedCountLabel": { - "message": "Show the number of blocked requests on the toolbar icon", + "message": "Dangos nifer y ceisiadau bloc ar eicon y bar offer", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "Enable strict blocking", + "message": "Galluogi blocio llym", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "Bydd llywio i safleoedd a allai fod yn annymunol yn cael ei rwystro, a byddwch yn cael y dewis i fwrw ymlaen.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Galluogi blocio pob-wybrennau", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Pan fydd yn weithredol, bydd hidlau sy'n cyfateb yn cau tabiau porwr diangen a grëir gan wefannau yn awtomatig.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Blwch tywod creu hidl", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Modd datblygwr", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "Yn galluogi mynediad i nodweddion sy'n addas ar gyfer defnyddwyr technegol.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "Copia wrth gefn", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "Copïwch eich gosodiadau arferol i ffeil, neu adferwch eich gosodiadau arferol o ffeil.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "Bydd adfer yn trosysgrifo holl gosodiadau arferol presennol.", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "Find lists", + "message": "Dod o hyd i restrau", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { @@ -284,19 +324,19 @@ "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite has prevented the following page from loading:", + "message": "Mae uBO Lite wedi atal y dudalen ganlynol rhag llwytho:", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "The page was blocked because of a matching filter in {{listname}}.", + "message": "Cafodd y dudalen ei rhwystro oherwydd hidl sy'n cyfateb yn {{listname}}.", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "Mae'r dudalen rwystredig am ailgyfeirio i safle arall. Os dewiswch fwrw ymlaen, byddwch yn llywio'n uniongyrchol i: {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { - "message": "without parameters", + "message": "heb baramedrau", "description": "Label to be used for the parameter-less URL" }, "strictblockBack": { @@ -316,7 +356,7 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Galluogi'r modd saethu elfen", + "message": "Tynnu elfen", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { @@ -324,11 +364,11 @@ "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "Creu hidl arferol", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "Tynnu hidl arferol", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { @@ -336,23 +376,23 @@ "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "Manylion modd hidlo", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "Rheolau DNR arferol", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "Rheolau DNR …", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "Set rheolau deinamig", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "Set rheolau sesiwn", "description": "An option in a dropdown list" }, "saveButton": { @@ -368,7 +408,7 @@ "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Import and append…", + "message": "Mewnforio ac atodi…", "description": "Text for buttons used to import and append content" }, "exportButton": { @@ -376,31 +416,31 @@ "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "Copïo wrth gefn…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "Adfer…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "Ailosod i osodiadau diofyn…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "Bydd eich holl osodiadau arferol yn cael eu tynnu. Ydych chi wir eisiau ailosod i osodiadau diofyn?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "Peidiwch â ychwanegu cynnwys o ffynonellau anniogel", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "Nifer y rheolau wedi'u cofrestru: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "Symudwch y llithrydd i ddewis y gêm orau", "description": "Label to describe the purpose of the slider" }, "pickerPick": { @@ -416,7 +456,7 @@ "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "Dewiswch hidl isod i amlygu elfennau sy'n cyfateb yn y dudalen we. Cliciwch y bin sbwriel i dynnu hidl.", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/da/messages.json b/platform/mv3/extension/_locales/da/messages.json index 8f0ba1e451155..3d48be14e2aa0 100644 --- a/platform/mv3/extension/_locales/da/messages.json +++ b/platform/mv3/extension/_locales/da/messages.json @@ -35,6 +35,10 @@ "message": "Fortrolighedspolitik", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Dokumentation", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "filtreringstilstand", "description": "Label in the popup panel for the current filtering mode" @@ -87,14 +91,34 @@ "message": "Regioner, sprog", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Importerede lister", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Tilføj filterliste…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL'en til filterlisten, der skal tilføjes", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "For at håndhæve kosmetiske eller scriptlets-filtre fra importerede lister skal uBlock gives tilladelse til at afvikle bruger-scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Import/ Eksport", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Indsæt bestemte kosmetiske filtre hér for at tilføje", + "message": "Bestemte kosmetiske/scriplets-filtre, som skal tilføjes", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Åbn webbrowserens udvidelsesside (chrome://extensions i Chrome eller Om:tilføjelser i Firefox), åbn uBO Lite-detaljerne, og slå Tillad bruger-scripts til (også kaldet “ubekræftede tredjeparts-scripts”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Ændringslog", "description": "" @@ -255,6 +279,22 @@ "message": "Navigering til potentielt uønskede websteder blokeres, men man tilbydes muligheden for at fortsætte.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Aktivér pop op-blokering", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Når aktiv, lukker matchende filtre automatisk uønskede webbrowserfaner åbnet af websteder.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Sandkasse til filteroprettelse", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "For at håndhæve kosmetiske eller scriptlets-filtre fra sandkasse skal uBlock gives tilladelse til at afvikle bruger-scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Udviklertilstand", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/de/messages.json b/platform/mv3/extension/_locales/de/messages.json index 3df12ad9542c1..7021c6c619289 100644 --- a/platform/mv3/extension/_locales/de/messages.json +++ b/platform/mv3/extension/_locales/de/messages.json @@ -28,13 +28,17 @@ "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { - "message": "Über", + "message": "Informationen", "description": "appears as tab name in dashboard" }, "aboutPrivacyPolicy": { "message": "Datenschutzhinweise", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Dokumentation", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "Filtermodus", "description": "Label in the popup panel for the current filtering mode" @@ -87,14 +91,34 @@ "message": "Regionen, Sprachen", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Importierte Listen", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Filterliste hinzufügen …", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL der Filterliste hier einfügen", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "Um kosmetische Filter oder Scriptlet-Filter aus importierten Listen anzuwenden, benötigt uBO Lite die Berechtigung zum Ausführen von Nutzerscripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Importieren und exportieren", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Kosmetische Filter oder Scriptlets zum Hinzufügen einfügen", + "message": "Kosmetische Filter oder Scriptlets hier einfügen", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Die Option befindet sich in den Browser-Einstellungen für Erweiterungen (chrome://extensions in Chrome oder about:addons in Firefox). Anschließend die Details von uBO Lite öffnen und Nutzerscripts zulassen aktivieren (in Firefox „Nicht verifizierten Skripten von Drittanbietern den Zugriff auf Ihre Daten erlauben“).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Änderungsprotokoll", "description": "" @@ -255,6 +279,22 @@ "message": "Die Navigation zu potenziell unerwünschten Websites wird verhindert, jedoch wird eine Möglichkeit zum Fortfahren angeboten.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Pop-ups blockieren", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Dadurch werden unerwünschte Browser-Tabs, die durch Websites geöffnet wurden, mithilfe von Filtern geschlossen.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Testumgebung zum Erstellen von Filtern", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "Um kosmetische Filter oder Scriptlet-Filter aus der Sandbox anzuwenden, benötigt uBO Lite die Berechtigung zum Ausführen von Nutzerscripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Entwicklermodus", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/el/messages.json b/platform/mv3/extension/_locales/el/messages.json index 79f0151df4f38..2fe24a838281d 100644 --- a/platform/mv3/extension/_locales/el/messages.json +++ b/platform/mv3/extension/_locales/el/messages.json @@ -4,7 +4,7 @@ "description": "extension name." }, "extShortDesc": { - "message": "Ένα πειραματικό εργαλείο φραγής περιεχομένου χωρίς δικαιώματα. Αποκλείει διαφημίσεις, ιχνηλάτες και πολλά άλλα μετά την εγκατάσταση.", + "message": "Ένα αποδοτικό πρόγραμμα φραγής περιεχομένου. Αποκλείει διαφημίσεις, ιχνηλάτες, εξορύκτες και άλλα αμέσως μετά την εγκατάσταση.", "description": "this will be in the Chrome web store: must be 132 characters or less" }, "perRulesetStats": { @@ -28,23 +28,27 @@ "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { - "message": "Σχετικά", + "message": "Πληροφορίες", "description": "appears as tab name in dashboard" }, "aboutPrivacyPolicy": { "message": "Πολιτική απορρήτου", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Οδηγίες", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "λειτουργία φιλτραρίσματος", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "Για αυτόν τον ιστότοπο", + "message": "Σε αυτόν τον ιστότοπο", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "Αναφορά ενός ζητήματος σε αυτόν τον ιστότοπο", + "message": "Αναφορά σφάλματος", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { @@ -87,14 +91,34 @@ "message": "Περιοχές, γλώσσες", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Εισαγόμενες λίστες φίλτρων", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Προσθήκη λίστας φίλτρων…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Επικολλήστε το URL της λίστας φίλτρων εδώ", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "Για να επιβάλετε φίλτρα μορφοποίησης ή σεναρίων από εισαγόμενες λίστες, πρέπει να δώσετε άδεια εκτέλεσης σεναρίων χρήστη στο uBO Lite.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Εισαγωγή / Εξαγωγή", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Επικολλήστε εδώ για προσθέσετε φίλτρα για συγκεκριμένα διακοσμητικά", + "message": "Επικολλήστε εδώ συγκεκριμένα φίλτρα μορφοποίησης ή σεναρίων για προσθήκη", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Ανοίξτε τη σελίδα επεκτάσεων του προγράμματος περιήγησής σας (chrome://extensions στο Chrome ή about:addons στον Firefox), ανοίξτε τις λεπτομέρειες του uBO Lite και ενεργοποιήστε την επιλογή Να επιτρέπονται τα user scripts (γνωστά και ως «μη επαληθευμένα σενάρια τρίτων»).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Αρχείο αλλαγών", "description": "" @@ -124,7 +148,7 @@ "description": "Shown in the About pane" }, "supportS6H": { - "message": "Αναφορά προβλήματος φίλτρου", + "message": "Αναφορά σφάλματος φίλτρου", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { @@ -140,7 +164,7 @@ "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Βρείτε παρόμοιες αναφορές στο GitHub", + "message": "Εύρεση παρόμοιων αναφορών στο GitHub", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { @@ -168,7 +192,7 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Έχει ζητήματα σχετικά με το απόρρητο", + "message": "Έχει σφάλματα σχετικά με το απόρρητο", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { @@ -188,7 +212,7 @@ "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Δημιουργία νέας αναφοράς", + "message": "Δημιουργία νέας αναφοράς στο GitHub", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { @@ -228,7 +252,7 @@ "description": "This describes the 'complete' filtering mode" }, "noFilteringModeDescription": { - "message": "Λίστα των hostnames για τα οποία δεν θα πραγματοποιηθεί φιλτράρισμα", + "message": "Λίστα ιστότοπων για τους οποίους δεν θα πραγματοποιείται φιλτράρισμα.", "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { @@ -248,19 +272,35 @@ "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "Ενεργοποίηση αυστηρής φραγής", + "message": "Ενεργοποίηση αυστηρού αποκλεισμού", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { "message": "Θα απετραπεί η πρόσβαση σε πιθανά ανεπιθύμητους ιστοτόπους. Θα σας προσφερθεί η επιλογή να συνεχίσετε.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Ενεργοποίηση αποκλεισμού αναδυόμενων", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Όταν είναι ενεργή, θα κλείνονται αυτόματα οι ανεπιθύμητες καρτέλες που δημιουργούν ιστοσελίδες οι οποίες αντιστοιχούν σε φίλτρα.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Περιβάλλον προστατευμένης εκτέλεσης για δημιουργία φίλτρων", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "Για να επιβάλετε φίλτρα μορφοποίησης ή σεναρίων από το περιβάλλον προστατευμένης εκτέλεσης, πρέπει να δώσετε άδεια εκτέλεσης σεναρίων χρήστη στο uBO Lite.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Λειτουργία προγραμματιστή", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Ενεργοποίηση πρόσβασης σε δυνατότητες κατάλληλες για τεχνικούς χρήστες.", + "message": "Ενεργοποιεί πρόσβαση σε δυνατότητες κατάλληλες για τεχνικούς χρήστες.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { @@ -316,7 +356,7 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Είσοδος σε λειτουργία αφαίρεσης στοιχείων", + "message": "Αφαίρεση ενός στοιχείου", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { diff --git a/platform/mv3/extension/_locales/en/messages.json b/platform/mv3/extension/_locales/en/messages.json index f6d9c00d5ba7d..df73d7ab8cf66 100644 --- a/platform/mv3/extension/_locales/en/messages.json +++ b/platform/mv3/extension/_locales/en/messages.json @@ -35,6 +35,10 @@ "message": "Privacy policy", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Documentation", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "filtering mode", "description": "Label in the popup panel for the current filtering mode" @@ -87,14 +91,34 @@ "message": "Regions, languages", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Imported lists", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Add filter list…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL of the filter list to add", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Import / Export", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "Specific cosmetic/scriptlet filters to add", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Open your browser's extensions page (chrome://extensions in Chrome or about:addons in Firefox), open uBO Lite details, and toggle on Allow user scripts (also referred to as “unverified third-party scripts”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Changelog", "description": "" @@ -255,6 +279,22 @@ "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Enable pop-up blocking", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "When active, matching filters will automatically close unwanted browser tabs created by websites.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Filter-creation sandbox", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Developer mode", "description": "Label for a checkbox in the options page" @@ -295,11 +335,11 @@ "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", "description": "Text warning about an incoming redirect" }, - "strictblockNoParamsPrompt": { + "strictblockNoParamsPrompt": { "message": "without parameters", "description": "Label to be used for the parameter-less URL" }, - "strictblockBack": { + "strictblockBack": { "message": "Go back", "description": "A button to go back to the previous web page" }, diff --git a/platform/mv3/extension/_locales/en_GB/messages.json b/platform/mv3/extension/_locales/en_GB/messages.json index 82722b33987d0..ce0a26c2fa297 100644 --- a/platform/mv3/extension/_locales/en_GB/messages.json +++ b/platform/mv3/extension/_locales/en_GB/messages.json @@ -35,6 +35,10 @@ "message": "Privacy policy", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Documentation", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "filtering mode", "description": "Label in the popup panel for the current filtering mode" @@ -44,7 +48,7 @@ "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "Report an issue on this website", + "message": "Report an issue", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { @@ -87,14 +91,34 @@ "message": "Regions, languages", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Imported lists", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Add filter list…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL of the filter list to add", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Import / Export", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic filters to add", + "message": "Specific cosmetic/scriptlet filters to add", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Open your browser's extensions page (chrome://extensions in Chrome or about:addons in Firefox), open the uBO Lite details, and toggle on Allow user scripts (also referred to as “unverified third-party scripts”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Change-log", "description": "" @@ -140,7 +164,7 @@ "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Find similar reports", + "message": "Find similar reports on GitHub", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { @@ -188,7 +212,7 @@ "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Create new report", + "message": "Create new report on GitHub", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { @@ -228,7 +252,7 @@ "description": "This describes the 'complete' filtering mode" }, "noFilteringModeDescription": { - "message": "List of hostnames for which no filtering will take place", + "message": "List of websites for which no filtering will take place.", "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { @@ -255,12 +279,28 @@ "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Enable pop-up blocking", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "When active, matching filters will automatically close unwanted browser tabs created by websites.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Filter-creation sandbox", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Developer mode", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enable access to features suitable for technical users.", + "message": "Enables access to features suitable for technical users.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { @@ -316,7 +356,7 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Enter element zapper mode", + "message": "Remove an element", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { @@ -376,7 +416,7 @@ "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Backup…", + "message": "Back up…", "description": "Text for buttons used to back up content" }, "restoreButton": { diff --git a/platform/mv3/extension/_locales/eo/messages.json b/platform/mv3/extension/_locales/eo/messages.json index c7384bc520fe8..cd50d410bf79b 100644 --- a/platform/mv3/extension/_locales/eo/messages.json +++ b/platform/mv3/extension/_locales/eo/messages.json @@ -4,15 +4,15 @@ "description": "extension name." }, "extShortDesc": { - "message": "An efficient content blocker. Blocks ads, trackers, miners, and more immediately upon installation.", + "message": "Rendimenta reklamoblokilo. Blokas reklamoj, spuriloj, miniloj de ĉifromono, kaj pli, tuj tiam instalis.", "description": "this will be in the Chrome web store: must be 132 characters or less" }, "perRulesetStats": { - "message": "{{ruleCount}} rules, converted from {{filterCount}} network filters", + "message": "{{ruleCount}} reguloj, konvertinte de {{filterCount}} retfiltriloj", "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "dashboardName": { - "message": "uBO Lite — Dashboard", + "message": "uBO Lite — Panelo", "description": "English: uBO Lite — Dashboard" }, "settingsPageName": { @@ -20,11 +20,11 @@ "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "Custom filters", + "message": "Propraj filtriloj", "description": "appears as tab name in dashboard" }, "developPageName": { - "message": "Develop", + "message": "Erarserĉilo", "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { @@ -32,23 +32,27 @@ "description": "appears as tab name in dashboard" }, "aboutPrivacyPolicy": { - "message": "Privacy policy", + "message": "Reguloj pri privateco", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Documentation", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { - "message": "filtering mode", + "message": "reĝimo de filtrado", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "On this website", + "message": "En tiu ĉi retejo", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "Report an issue", + "message": "Raporti problemon", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { - "message": "Open the dashboard", + "message": "Malfermi la stirpanelon", "description": "English: Click to open the dashboard" }, "popupMoreButton": { @@ -72,29 +76,49 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Malware protection, security", + "message": "Protekto kontraŭ fiprogramaro, sekureco", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { - "message": "Annoyances", + "message": "Ĝenoj", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMisc": { - "message": "Miscellaneous", + "message": "Diversaĵoj", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupRegions": { - "message": "Regions, languages", + "message": "Regionoj, lingvoj", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "3pGroupImported": { + "message": "Imported lists", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "customListImportLabel": { + "message": "Add filter list…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL of the filter list to add", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { - "message": "Import / Export", + "message": "Importi / Eksporti", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "Kopiu ĉi tien apartaj ornamaj filtriloj por aldoni ilin", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Open your browser's extensions page (chrome://extensions in Chrome or about:addons in Firefox), open uBO Lite details, and toggle on Allow user scripts (also referred to as “unverified third-party scripts”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Ŝanĝprotokolo", "description": "" @@ -116,91 +140,91 @@ "description": "Link text to translations repo" }, "aboutFilterLists": { - "message": "Filter lists", + "message": "Listoj de filtriloj", "description": "Link text to uBO's own filter lists repo" }, "aboutDependencies": { - "message": "External dependencies (GPLv3-compatible):", + "message": "Eksteraj dependaĵoj (kongruaj kun GPLv3):", "description": "Shown in the About pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "Raporti problemon de filtrado", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "Raportu problemojn pri specifaj retejoj ĉe la cimspurilo uBlockOrigin/uAssets. Tio postulas konton ĉe GitHub.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting information", + "message": "Informo pri problemsolvado", "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "Por eviti ŝarĝi volontulojn per duplikataj raportoj, bonvolu konfirmi ke la problemo ankoraŭ ne raportitas. Noto: klaki la butonon kaŭzas ke la HTTP-origino de la paĝo senditas al GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "Serĉi similajn raportojn ĉe GitHub", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "Adreso de la retpaĝo:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "La retpaĝo…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- Elektu ion --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "Videblas reklamoj aŭ restaĵoj de reklamoj", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "Havas plustavolojn aŭ aliajn ĝenaĵojn", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBO Lite", + "message": "Detektas uBO Lite", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "Havas problemojn pri privateco", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBO Lite is enabled", + "message": "Misfunkcias, se uBO Lite estas ŝaltita", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "Malfermas nedeziratajn langetojn aŭ fenestrojn", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "Sekvas malbon-programoj, trompo-retejoj", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "Indiki ke la retpaĝo estas nelabortaŭga", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "Krei novan raporton ĉe GitHub", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { - "message": "Default filtering mode", + "message": "Defaŭlta reĝimo de filtrado", "description": "The header text for the default filtering mode section" }, "defaultFilteringModeDescription": { - "message": "The default filtering mode will be overridden by per-website filtering modes. You can adjust the filtering mode on any given website according to whichever mode works best on that website. Each mode has its advantages and disadvantages.", + "message": "La defaŭltan reĝimon de filtrado superregas la retejo-specifa reĝimo de filtrado. Vi povas agordi la reĝimon po-reteje por la plej bona funkciado. Ĉiu reĝimo havas utilojn kaj malutilojn.", "description": "This describes the default filtering mode setting" }, "filteringMode0Name": { - "message": "no filtering", + "message": "neniu filtrado", "description": "Name of blocking mode 0" }, "filteringMode1Name": { @@ -208,215 +232,231 @@ "description": "Name of blocking mode 1" }, "filteringMode2Name": { - "message": "optimal", + "message": "plej bona", "description": "Name of blocking mode 2" }, "filteringMode3Name": { - "message": "complete", + "message": "plena", "description": "Name of blocking mode 3" }, "basicFilteringModeDescription": { - "message": "Basic network filtering from selected filter lists.\n\nDoes not require permission to read and modify data on websites.", + "message": "Simpla reta filtrado per elektitaj filtriloj.\n\nNe postulas la permeson legi kaj redakti datumojn de ĉiuj retejoj.", "description": "This describes the 'basic' filtering mode" }, "optimalFilteringModeDescription": { - "message": "Advanced network filtering plus specific extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.", + "message": "Kompleksa reta filtrado plus plua filtrado per elektitaj filtriloj.\n\nPostulas la permeson legi kaj redakti datumojn de ĉiuj retejoj.", "description": "This describes the 'optimal' filtering mode" }, "completeFilteringModeDescription": { - "message": "Advanced network filtering plus specific and generic extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.\n\nGeneric extended filtering may cause higher web page resources usage.", + "message": "Kompleksa reta filtrado plus specifa kaj ĝenerala plua filtrado per elektitaj filtriloj.\n\nPostulas la permeson legi kaj redakti datumojn de ĉiuj retejoj.\n\nĜenerala plua filtrado eble kaŭzas pliigi kvanton de uzataj retejaj rimedoj.", "description": "This describes the 'complete' filtering mode" }, "noFilteringModeDescription": { - "message": "List of websites for which no filtering will take place.", + "message": "Listo de retejoj por kiuj neniu filtrado okazos.", "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { - "message": "[hostnames only]\nexample.com\ngames.example\n...", + "message": "[nur domajnoj]\nekzemple.com\nludoj.ekzemple\n...", "description": "Default text for in edit field" }, "behaviorSectionLabel": { - "message": "Behavior", + "message": "Agmaniero", "description": "The header text for the 'Behavior' section" }, "autoReloadLabel": { - "message": "Automatically reload page when changing filtering mode", + "message": "Aŭtomate reŝargi la paĝon ŝanĝinte reĝimon de filtrado", "description": "Label for a checkbox in the options page" }, "showBlockedCountLabel": { - "message": "Show the number of blocked requests on the toolbar icon", + "message": "Montri la nombron de blokitaj petoj sur la bildsimbolo", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "Enable strict blocking", + "message": "Ŝalti striktan blokadon", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "La navigadon al eble nevolaj retejoj blokos, kaj vi povos elekti procedi.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Ŝalti blokadon de ŝprucfenestroj", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Dum ŝaltita, kongruaj filtriloj aŭtomate fermas nevolitajn langetojn kiujn kreas retejoj.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Provejo por kreado de filtriloj", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Developer mode", + "message": "Reĝimo por programistoj", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "Permesas atingi funkciojn taŭgajn por spertuloj.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "Savkopiado", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "Savkopii viajn proprajn agordojn en dosieron, aŭ restaŭri viajn proprajn agordojn el dosiero.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "Restaŭrado anstataŭigas viajn nunajn proprajn agordojn.", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "Find lists", + "message": "Trovi listojn", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { - "message": "Page blocked", + "message": "Paĝon blokis", "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite has prevented the following page from loading:", + "message": "uBO Lite blokas la ŝargadon de la sekva paĝo:", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "The page was blocked because of a matching filter in {{listname}}.", + "message": "La paĝon blokis ĉar estas kongrua filtrilo en {{listname}}.", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "La blokita paĝo volas fordirekti al alia retejo. Se vi daŭras, vi navigos senpere al {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { - "message": "without parameters", + "message": "sen parametroj", "description": "Label to be used for the parameter-less URL" }, "strictblockBack": { - "message": "Go back", + "message": "Reen", "description": "A button to go back to the previous web page" }, "strictblockClose": { - "message": "Close this window", + "message": "Fermi tiun ĉi fenestron", "description": "A button to close the current tab" }, "strictblockDontWarn": { - "message": "Don't warn me again about this site", + "message": "Ne plu avertu min pri tiu ĉi retejo", "description": "Label for checkbox in document-blocked page" }, "strictblockProceed": { - "message": "Proceed", + "message": "Procedi", "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Remove an element", + "message": "Forigi elementon", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Exit element zapper mode", + "message": "Eliri la reĝimon de forigo de elementoj", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "Krei propran filtrilon", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "Forigi propran filtrilon", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { - "message": "View:", + "message": "Vido:", "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "Detaloj de reĝimo de filtrado", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "Propraj reguloj de DNR", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "DNR reguloj de …", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "Dinamika regularo", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "Regularo de seanco", "description": "An option in a dropdown list" }, "saveButton": { - "message": "Save", + "message": "Konservi", "description": "Text for buttons used to save changes" }, "revertButton": { - "message": "Revert", + "message": "Malfari", "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "Add", + "message": "Aldoni", "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Import and append…", + "message": "Importi kaj postaldoni…", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Export…", + "message": "Eksporti…", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "Savkopii…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "Restaŭri…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "Remeti normajn agordojn…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "Ĉiuj viaj propraj agordoj foriĝos. Ĉu vi vere volas remeti normajn agordojn?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "Ne aldonu regulojn el ne fidindaj fontoj", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "Nombro de registrataj reguloj: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "Movi la glitilon por elekti la plej bonan filtrilon", "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Pick", + "message": "Elekti", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "Antaŭrigardi", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "Krei", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "Elektu filtrilon suban por lumigi kongruajn elementojn en la retejo. Alklaku la rubujon por forigi filtrilon.", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/es/messages.json b/platform/mv3/extension/_locales/es/messages.json index 6b927cf29a76a..733bb1306fdc8 100644 --- a/platform/mv3/extension/_locales/es/messages.json +++ b/platform/mv3/extension/_locales/es/messages.json @@ -35,6 +35,10 @@ "message": "Política de privacidad", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Documentación", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "modo de filtrado", "description": "Label in the popup panel for the current filtering mode" @@ -87,6 +91,22 @@ "message": "Regiones, idiomas", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Listas importadas", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Agregar filtro de lista…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Pega aquí la URL del filtro de lista a agregar", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "Para hacer respetar los filtros cosméticos o de scripts a partir de listas importadas, debes otorgar a uBO Lite permiso para ejecutar scripts de usuario.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Importar / Exportar", "description": "Text label heading the import/export area of custom filters" @@ -95,6 +115,10 @@ "message": "Pega aquí los filtros cosméticos específicos a añadir", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Abre la página de extensiones de tu navegador. (chrome://extensions en Chrome o about:addons en Firefox), abre los uBO Lite detalles, y enciende Permitir scripts de usuario (tambien referido como \"scripts de terceros no verificados\").", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Registro de cambios", "description": "" @@ -255,6 +279,22 @@ "message": "La navegación a sitios potencialmente no deseados será bloqueada, y se te ofrecerá la opción de continuar.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Habilitar el bloqueo de emergentes", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Cuando está activo, los filtros que coincidan cerraran automáticamente las pestañas no solicitadas creadas por los sitios web.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Caja de arena de creación de filtro", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "Para hacer respetar los filtros cosméticos o de scripts desde el entorno aislado, debes otorgar a uBO Lite permiso para ejecutar scripts de usuario.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Modo desarrollador", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/et/messages.json b/platform/mv3/extension/_locales/et/messages.json index 5d6eaa33886ca..67b850da0c03b 100644 --- a/platform/mv3/extension/_locales/et/messages.json +++ b/platform/mv3/extension/_locales/et/messages.json @@ -35,6 +35,10 @@ "message": "Privaatsusteatis", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Dokumendid", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "filtreerimisrežiim", "description": "Label in the popup panel for the current filtering mode" @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Pahavara domeenid", + "message": "Pahavara tõkestamine, turvalisus", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,14 +91,34 @@ "message": "Regioonid, keeled", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Imporditud nimekirjad", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Lisa filtri nimekiri…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Lisata filtri nimekirja URL", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Impordi/ekspordi", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Kindlate kosmeetiliste filtrite lisamiseks asetage need siia", + "message": "Kindlate kosmeetiliste/scriptlet filtrite lisamiseks asetage need siia", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Ava veebilehitseja laiendite lehekülg (chrome://extensions Chrome'is või about:addons Firefoxis), ava uBO Lite'i andmed ja luba Luba kasutajaskriptid (tuntud ka kui „kinnitamata muu osapoole skriptid“).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Muudatuste logi", "description": "" @@ -255,6 +279,22 @@ "message": "Kahtlastele veebilehtedele suunamist takistatakse ja pakutakse võimalust jätkamiseks.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Luba hüpikute tõkestamine", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Lubamisel sulgevad ühtivad filtrid veebisaitide loodud soovimatud brauseri vahekaardid automaatselt.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Filtri loomise katsetus", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Arendaja režiim", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/eu/messages.json b/platform/mv3/extension/_locales/eu/messages.json index 162073c53a2a0..224b809a3055d 100644 --- a/platform/mv3/extension/_locales/eu/messages.json +++ b/platform/mv3/extension/_locales/eu/messages.json @@ -20,11 +20,11 @@ "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "Custom filters", + "message": "Iragazki pertsonalizatuak", "description": "appears as tab name in dashboard" }, "developPageName": { - "message": "Develop", + "message": "Garapena", "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { @@ -35,12 +35,16 @@ "message": "Pribatutasun politika", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Dokumentazioa", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "Iragazteko modua", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "On this website", + "message": "Webgune honetan", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Malware domeinuak", + "message": "Malwarearen aurkako babesa, segurtasuna", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,14 +91,34 @@ "message": "Eskualdeak, hizkuntzak", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Inportatutako zerrendak", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Gehitu iragazki-zerrenda…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Gehitzeko iragazki-zerrendaren URLa", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { - "message": "Import / Export", + "message": "Inportatu / Esportatu", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "Gehitzeko iragazki kosmetiko/scriptlet zehatzak", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Ireki zure nabigatzailearen luzapenen orria (chrome://extensions Chrome-n edo about:addons Firefox-en), ireki uBO Lite-ren xehetasunak, eta aktibatu Onartu erabiltzaile-scriptak (“egiaztatu gabeko hirugarrenen scriptak” ere deitua).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Aldaketen erregistroa", "description": "" @@ -128,39 +152,39 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "Webgune zehatzekin iragazki-arazoen berri eman uBlockOrigin/uAssets arazo-jarraitzaileari. GitHub kontua behar da.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting information", + "message": "Arazoak konpontzeko informazioa", "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "Bikoiztutako txostenekin boluntarioei lana ez emateko, egiaztatu arazoa ez dela aurretik jakinarazi. Oharra: botoian klik eginez gero, orriaren jatorria GitHub-era bidaliko da.", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "Antzeko txostenak aurkitu GitHub-en", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "Web orriaren helbidea:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "Web orria…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- Aukeratu sarrera bat --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "Iragarkiak edo iragarki-hondarrak erakusten ditu", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "Gainjarriak edo bestelako traba-ak ditu", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { @@ -168,27 +192,27 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "Pribatutasun-arazoak ditu", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBO Lite is enabled", + "message": "Matxurak ditu uBO Lite gaituta dagoenean", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "Nahi gabeko fitxak edo leihoak irekitzen ditu", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "Software kaltegarrietara eta phishing-era darama", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "Markatu web orria “NSFW” gisa (“Lanerako segurua ez”)", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "Sortu txosten berria GitHub-en", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { @@ -248,35 +272,51 @@ "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "Enable strict blocking", + "message": "Gaitu blokeatze zorrotza", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "Nahi ez diren guneetarako nabigazioa blokeatu egingo da, eta jarraitzeko aukera eskainiko zaizu.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Gaitu pop-up blokeoa", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Aktibatuta dagoenean, bat datozen iragazkiek automatikoki itxiko dituzte webguneek sortutako nahi gabeko nabigatzaile-fitxak.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Iragazkiak sortzeko proba-gunea", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Developer mode", + "message": "Garatzaile modua", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "Erabiltzaile teknikoentzako egokiak diren funtzioetarako sarbidea gaitzen du.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "Babeskopia", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "Egin babeskopia zure ezarpen pertsonalizatuen fitxategi batean, edo leheneratu zure ezarpen pertsonalizatuak fitxategi batetik.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "Leheneratzeak zure egungo ezarpen pertsonalizatu guztiak gainidatziko ditu.", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "Find lists", + "message": "Bilatu zerrendak", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { @@ -284,15 +324,15 @@ "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite has prevented the following page from loading:", + "message": "uBO Lite-k hurrengo orria kargatzea eragotzi du:", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "The page was blocked because of a matching filter in {{listname}}.", + "message": "Orria blokeatu da {{listname}} zerrendan bat datorren iragazki bat dagoelako.", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "Blokeatutako orriak beste gune batera berbideratu nahi du. Jarraitzea erabakitzen baduzu, zuzenean nabigatuko duzu hona: {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { @@ -316,7 +356,7 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Sartu elementua zapper moduan", + "message": "Elementu bat kendu", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { @@ -324,99 +364,99 @@ "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "Sortu iragazki pertsonalizatu bat", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "Kendu iragazki pertsonalizatu bat", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { - "message": "View:", + "message": "Ikusi:", "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "Iragazte moduaren xehetasunak", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "DNR arau pertsonalizatuak", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "…-ren DNR arauak", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "Arau-multzo dinamikoa", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "Saioaren arau-multzoa", "description": "An option in a dropdown list" }, "saveButton": { - "message": "Save", + "message": "Gorde", "description": "Text for buttons used to save changes" }, "revertButton": { - "message": "Revert", + "message": "Desegin", "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "Add", + "message": "Gehitu", "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Import and append…", + "message": "Inportatu eta erantsi…", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Export…", + "message": "Esportatu…", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "Egin babeskopia…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "Leheneratu…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "Berrezarri ezarpen lehenetsietara…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "Zure ezarpen pertsonalizatu guztiak kenduko dira. Benetan lehenetsitako ezarpenetara berrezarri nahi duzu?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "Ez gehitu edukirik iturri fidagarririk gabekoetatik", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "Erregistratutako arau kopurua: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "Mugitu graduatzailea bat etorritako onena hautatzeko", "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Pick", + "message": "Aukeratu", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "Aurrebista", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "Sortu", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "Hautatu beheko iragazki bat web orrian bat datozen elementuak nabarmentzeko. Egin klik zakarrontzian iragazki bat kentzeko.", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/fa/messages.json b/platform/mv3/extension/_locales/fa/messages.json index e13089f186f9d..5ebdfa7062255 100644 --- a/platform/mv3/extension/_locales/fa/messages.json +++ b/platform/mv3/extension/_locales/fa/messages.json @@ -8,11 +8,11 @@ "description": "this will be in the Chrome web store: must be 132 characters or less" }, "perRulesetStats": { - "message": "{{ruleCount}} rules, converted from {{filterCount}} network filters", + "message": "{{ruleCount}} قانون، تبدیل‌شده از {{filterCount}} فیلتر شبکه", "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "dashboardName": { - "message": "uBO Lite — Dashboard", + "message": "uBO Lite - داشبورد", "description": "English: uBO Lite — Dashboard" }, "settingsPageName": { @@ -20,11 +20,11 @@ "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "Custom filters", + "message": "فیلترهای سفارشی", "description": "appears as tab name in dashboard" }, "developPageName": { - "message": "Develop", + "message": "توسعه", "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { @@ -35,16 +35,20 @@ "message": "حریم خصوصی", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "مستندات", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { - "message": "filtering mode", + "message": "حالت فیلتر کردن", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "On this website", + "message": "در این وبسایت", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "Report an issue", + "message": "گزارش مشکلی", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { @@ -72,11 +76,11 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Malware protection, security", + "message": "محافظت در برابر بدافزار، امنیت", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { - "message": "Annoyances", + "message": "مزاحمت‌ها", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMisc": { @@ -87,14 +91,34 @@ "message": "مناطق، زبانها", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "لیست‌های وارد شده", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "وارد کردن لیست فیلتر…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "آدرس اینترنتی لیست فیلتر برای افزودن", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { - "message": "Import / Export", + "message": "وارد کردن / خارج کردن", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "فیلترهای ظاهری/اسکریپتلت خاص برای افزودن", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "صفحه افزونه‌های مرورگر خود را باز کنید (chrome://extensions در کروم یا about:addons در فایرفاکس)، جزئیات uBO Lite را باز کنید و گزینه اجازه به اسکریپت‌های کاربر (که به عنوان \"اسکریپت‌های شخص ثالث تایید نشده\" نیز شناخته می‌شود) را فعال کنید.", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "گزارش دگرگونی", "description": "" @@ -116,19 +140,19 @@ "description": "Link text to translations repo" }, "aboutFilterLists": { - "message": "Filter lists", + "message": "لیست‌های فیلتر", "description": "Link text to uBO's own filter lists repo" }, "aboutDependencies": { - "message": "External dependencies (GPLv3-compatible):", + "message": "وابستگی‌های خارجی (سازگار با GPLv3):", "description": "Shown in the About pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "گزارش اشکال در فیلتر", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "مشکلات فیلتر با وبسایت‌های مشخص را به ترکر مشکلات uBlockOrigin/uAssets گزارش دهید. نیازمند حساب گیت‌هاب است.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { @@ -136,11 +160,11 @@ "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "برای جلوگیری از تحمیل گزارش‌های تکراری به داوطلبان، لطفاً بررسی کنید که این مشکل قبلاً گزارش نشده باشد. توجه: کلیک بر روی این دکمه باعث می‌شود که مبدأ صفحه به گیت‌هاب ارسال شود.", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "یافتن گزارش‌های مشابه در گیت‌هاب", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { @@ -148,7 +172,7 @@ "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "صفحه وب...", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { @@ -164,7 +188,7 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBO Lite", + "message": "شناسایی uBO Lite", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { @@ -172,7 +196,7 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBO Lite is enabled", + "message": "هنگام فعال بودن uBO Lite دچار نقص می‌شود", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { @@ -184,239 +208,255 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "برچسب‌گذاری صفحه وب به عنوان \"NSFW\" (\"نامناسب برای محیط کار\")", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "ایجاد گزارش جدید در گیت‌هاب", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { - "message": "Default filtering mode", + "message": "حالت پیش‌فرض فیلتر کردن", "description": "The header text for the default filtering mode section" }, "defaultFilteringModeDescription": { - "message": "The default filtering mode will be overridden by per-website filtering modes. You can adjust the filtering mode on any given website according to whichever mode works best on that website. Each mode has its advantages and disadvantages.", + "message": "حالت پیش‌فرض فیلتر کردن توسط حالت‌های فیلتر مخصوص هر سایت لغو خواهد شد. شما می‌توانید حالت فیلتر را در هر وب‌سایت مشخص، بر اساس حالتی که بهترین عملکرد را در آن سایت دارد، تنظیم کنید. هر حالت مزایا و معایب خاص خود را دارد.", "description": "This describes the default filtering mode setting" }, "filteringMode0Name": { - "message": "no filtering", + "message": "بدون فیلتر", "description": "Name of blocking mode 0" }, "filteringMode1Name": { - "message": "basic", + "message": "پایه", "description": "Name of blocking mode 1" }, "filteringMode2Name": { - "message": "optimal", + "message": "بهینه", "description": "Name of blocking mode 2" }, "filteringMode3Name": { - "message": "complete", + "message": "کامل", "description": "Name of blocking mode 3" }, "basicFilteringModeDescription": { - "message": "Basic network filtering from selected filter lists.\n\nDoes not require permission to read and modify data on websites.", + "message": "فیلتر کردن پایه شبکه از لیست‌های فیلتر انتخاب شده.\n\nنیازی به مجوز برای خواندن و تغییر داده‌ها در وب‌سایت‌ها ندارد.", "description": "This describes the 'basic' filtering mode" }, "optimalFilteringModeDescription": { - "message": "Advanced network filtering plus specific extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.", + "message": "فیلتر پیشرفته شبکه به علاوه فیلتر گسترده خاص از لیست‌های فیلتر انتخاب شده.\n\nبه مجوز گسترده برای خواندن و تغییر داده‌ها در تمام وب‌سایت‌ها نیاز دارد.", "description": "This describes the 'optimal' filtering mode" }, "completeFilteringModeDescription": { - "message": "Advanced network filtering plus specific and generic extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.\n\nGeneric extended filtering may cause higher web page resources usage.", + "message": "فیلتر پیشرفته شبکه به علاوه فیلتر گسترده خاص و عمومی از لیست‌های فیلتر انتخاب شده.\n\nبه مجوز گسترده برای خواندن و تغییر داده‌ها در تمام وب‌سایت‌ها نیاز دارد.\n\nفیلتر گسترده عمومی ممکن است باعث استفاده بیشتر از منابع صفحه وب شود.", "description": "This describes the 'complete' filtering mode" }, "noFilteringModeDescription": { - "message": "List of websites for which no filtering will take place.", + "message": "لیست وب‌سایت‌هایی که هیچ فیلتری برای آن‌ها اعمال نخواهد شد.", "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { - "message": "[hostnames only]\nexample.com\ngames.example\n...", + "message": "[فقط نام میزبان]\nexample.com\ngames.example\n...", "description": "Default text for in edit field" }, "behaviorSectionLabel": { - "message": "Behavior", + "message": "رفتار", "description": "The header text for the 'Behavior' section" }, "autoReloadLabel": { - "message": "Automatically reload page when changing filtering mode", + "message": "بارگذاری مجدد خودکار صفحه هنگام تغییر حالت فیلتر", "description": "Label for a checkbox in the options page" }, "showBlockedCountLabel": { - "message": "Show the number of blocked requests on the toolbar icon", + "message": "نمایش تعداد درخواست‌های مسدود شده روی آیکون نوار ابزار", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "Enable strict blocking", + "message": "فعال کردن مسدودسازی سخت‌گیرانه", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "پیمایش به سایت‌های بالقوه نامطلوب مسدود خواهد شد و به شما گزینه‌ای برای ادامه دادن پیشنهاد می‌شود.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "فعال کردن مسدودسازی پنجره‌های بازشو", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "هنگام فعال بودن، فیلترهای منطبق به طور خودکار تب‌های مرورگر ناخواسته ایجاد شده توسط وب‌سایت‌ها را می‌بندند.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "محیط آزمایشی ایجاد فیلتر", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Developer mode", + "message": "حالت توسعه‌دهنده", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "دسترسی به ویژگی‌های مناسب برای کاربران فنی را فعال می‌کند.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "پشتیبان‌گیری", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "از تنظیمات سفارشی خود در یک فایل پشتیبان بگیرید یا تنظیمات سفارشی خود را از یک فایل بازیابی کنید.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "بازیابی باعث رونویسی روی تمام تنظیمات سفارشی فعلی شما خواهد شد.", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "Find lists", + "message": "یافتن لیست‌ها", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { - "message": "Page blocked", + "message": "صفحه مسدود شد", "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite has prevented the following page from loading:", + "message": "uBO Lite از بارگذاری صفحه زیر جلوگیری کرده است:", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "The page was blocked because of a matching filter in {{listname}}.", + "message": "این صفحه به دلیل وجود یک فیلتر منطبق در {{listname}} مسدود شد.", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "صفحه مسدود شده می‌خواهد به سایت دیگری تغییر مسیر دهد. اگر ادامه دادن را انتخاب کنید، مستقیماً به اینجا هدایت می‌شوید: {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { - "message": "without parameters", + "message": "بدون پارامترها", "description": "Label to be used for the parameter-less URL" }, "strictblockBack": { - "message": "Go back", + "message": "بازگشت", "description": "A button to go back to the previous web page" }, "strictblockClose": { - "message": "Close this window", + "message": "بستن این پنجره", "description": "A button to close the current tab" }, "strictblockDontWarn": { - "message": "Don't warn me again about this site", + "message": "دیگر درباره این سایت به من هشدار نده", "description": "Label for checkbox in document-blocked page" }, "strictblockProceed": { - "message": "Proceed", + "message": "ادامه دادن", "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Remove an element", + "message": "حذف یک عنصر", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Exit element zapper mode", + "message": "خروج از حالت حذف عنصر", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "ایجاد یک فیلتر سفارشی", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "حذف یک فیلتر سفارشی", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { - "message": "View:", + "message": "مشاهده:", "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "جزئیات حالت فیلتر کردن", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "قوانین DNR سفارشی", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "قوانین DNR مربوط به ...", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "مجموعه قوانین پویا", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "مجموعه قوانین نشست", "description": "An option in a dropdown list" }, "saveButton": { - "message": "Save", + "message": "ذخیره", "description": "Text for buttons used to save changes" }, "revertButton": { - "message": "Revert", + "message": "بازگرداندن", "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "Add", + "message": "افزودن", "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Import and append…", + "message": "وارد کردن و افزودن...", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Export…", + "message": "صدور...", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "پشتیبان‌گیری...", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "بازیابی...", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "بازنشانی به تنظیمات پیش‌فرض...", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "تمام تنظیمات سفارشی شما حذف خواهد شد. آیا واقعاً می‌خواهید به تنظیمات پیش‌فرض بازنشانی کنید؟", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "از منابع نامعتبر محتوا اضافه نکنید", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "تعداد قوانین ثبت شده: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "نوار لغزنده را حرکت دهید تا بهترین تطابق را انتخاب کنید", "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Pick", + "message": "انتخاب", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "پیش‌نمایش", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "ایجاد", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "یک فیلتر را در زیر انتخاب کنید تا عناصر منطبق در صفحه وب برجسته شوند. روی سطل زباله کلیک کنید تا یک فیلتر حذف شود.", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/fi/messages.json b/platform/mv3/extension/_locales/fi/messages.json index b73a25994e58b..b0822be4598b6 100644 --- a/platform/mv3/extension/_locales/fi/messages.json +++ b/platform/mv3/extension/_locales/fi/messages.json @@ -35,6 +35,10 @@ "message": "Tietosuojakäytäntö", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Ohjeet", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "suodatustila", "description": "Label in the popup panel for the current filtering mode" @@ -87,14 +91,34 @@ "message": "Alueet, kielet", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Tuodut listat", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Lisää suodatinlista…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Lisättävän listan URL-osoite", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "Tuotujen listojen kosmeetisten ja scriplet‑suodattimien käyttämiseksi, on uBO Litelle myönnettävä oikeus suorittaa käyttäjäskriptejä.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Tuonti / Vienti", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Liitä lisättävät kosmeettiset suodattimet tähän", + "message": "Lisättävät kosmeettiset/scriptlet-suodattimet", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Avaa selaimesi laajennussivu (chrome://extensions Chromessa, about:addons Firefoxissa), valitse uBO Liten tiedot ja aktivoi käyttöoikeus Salli käyttäjäskriptit tai Salli vahvistamattomien kolmannen osapuolen komentosarjojen pääsy tietoihisi.", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Muutoshistoria", "description": "" @@ -228,7 +252,7 @@ "description": "This describes the 'complete' filtering mode" }, "noFilteringModeDescription": { - "message": "Listaus osotteista, joita ei suodateta.", + "message": "Listaus verkkosivustoista, joita ei suodateta.", "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { @@ -255,6 +279,22 @@ "message": "Potentiaalisesti ei-toivottujen sivustojen avaaminen estetään mahdollisuudella jatkaa.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Käytä ponnahdusestoa", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Kun käytössä, suljetaan suodattimia vastaavat verkkosivustojen avaamat ei-toivotut selaimen välilehdet automaattisesti.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Vapaa suodatinluonti", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "Vapaan suodatinluonnin kosmeetisten ja scriplet‑suodattimien käyttämiseksi, on uBO Litelle myönnettävä oikeus suorittaa käyttäjäskriptejä.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Kehittäjätila", "description": "Label for a checkbox in the options page" @@ -264,7 +304,7 @@ "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Varmuuskopioi / Palauta", + "message": "Varmuuskopiointi", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { diff --git a/platform/mv3/extension/_locales/fil/messages.json b/platform/mv3/extension/_locales/fil/messages.json index a2b3b9130c614..cb80fb29d5f0c 100644 --- a/platform/mv3/extension/_locales/fil/messages.json +++ b/platform/mv3/extension/_locales/fil/messages.json @@ -35,6 +35,10 @@ "message": "Patakaran sa pagkapribado", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Documentation", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "moda nang pagsasala", "description": "Label in the popup panel for the current filtering mode" @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Mga domain na may malware", + "message": "Proteksyon sa malware, seguridad", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,14 +91,34 @@ "message": "Mga rehiyon o wika", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Imported lists", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Add filter list…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL of the filter list to add", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Import / Export", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "Specific cosmetic/scriptlet filters to add", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Open your browser's extensions page (chrome://extensions in Chrome or about:addons in Firefox), open uBO Lite details, and toggle on Allow user scripts (also referred to as “unverified third-party scripts”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Talaan ng mga pagbabago", "description": "" @@ -255,6 +279,22 @@ "message": "Haharangan ang pagpunta sa mga hindi nais na mga site, at bibigyan ka ng pagkakataon na magpatuloy.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Enable pop-up blocking", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "When active, matching filters will automatically close unwanted browser tabs created by websites.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Filter-creation sandbox", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Developer mode", "description": "Label for a checkbox in the options page" @@ -316,7 +356,7 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Paganahin ang element zapper mode", + "message": "Mag-alis ng elemento", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { diff --git a/platform/mv3/extension/_locales/fr/messages.json b/platform/mv3/extension/_locales/fr/messages.json index f68a7b1e8f0e5..ae9e77634c3a6 100644 --- a/platform/mv3/extension/_locales/fr/messages.json +++ b/platform/mv3/extension/_locales/fr/messages.json @@ -35,6 +35,10 @@ "message": "Politique de confidentialité", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Documentation", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "Mode de filtrage", "description": "Label in the popup panel for the current filtering mode" @@ -87,14 +91,34 @@ "message": "Régions, langues", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Listes importées", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Ajouter une liste de filtres…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Lien de la liste de filtres à ajouter", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "Pour appliquer les filtres cosmétiques / scriptlets depuis les listes importées, vous devez accorder à uBO Lite la permission d'exécuter des scripts utilisateurs.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Importer / Exporter", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Coller ici les filtres cosmétiques spécifiques à ajouter", + "message": "Filtres cosmétiques/scriptlets spécifiques à ajouter", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Ouvrez la page des extensions de votre navigateur (chrome://extensions dans Chrome, ou about:addons dans Firefox), ouvrez la page des détails d'uBO Lite, et activez l'option Autoriser les scripts utilisateurs (aussi appelés \"scripts tiers non-vérifiés\").", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Journal des changements", "description": "" @@ -255,6 +279,22 @@ "message": "La navigation vers des sites potentiellement indésirables sera bloquée, et vous aurez la possibilité de continuer", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Activer le blocage pop-up", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Lorsque cette option est activée, les filtres correspondants fermeront automatiquement les onglets de navigateur indésirés créés par les sites Web.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Bac à sable de création de filtres", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "Pour appliquer les filtres cosmétiques / scriptlets depuis le bac à sable, vous devez accorder à uBO Lite la permission d'exécuter des scripts utilisateurs.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Mode développeur", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/fy/messages.json b/platform/mv3/extension/_locales/fy/messages.json index a39aef1a6f4a8..9367bbe1e7d07 100644 --- a/platform/mv3/extension/_locales/fy/messages.json +++ b/platform/mv3/extension/_locales/fy/messages.json @@ -35,6 +35,10 @@ "message": "Privacybelied", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Dokumintaasje", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "filtermodus", "description": "Label in the popup panel for the current filtering mode" @@ -87,14 +91,34 @@ "message": "Gebieden, talen", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Ymportearre listen", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Filterlist tafoegje…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL fan de ta te foegjen filterlist", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "Om kosmetyske of scriptletfilters fan ymportearre listen út ta te passen, moatte jo uBO Lite tastimming jaan foar it útfieren fan brûkersscripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Ymportearje / Eksportearje", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Plak hjir spesifike kosmetyske filters om ta te foegjen", + "message": "Spesifike kosmetyske of scriptletfilters om ta te foegjen", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Iepenje de útwreidingsside fan jo browser (chrome://extensions yn Chrome of about:addons yn Firefox), iepenje de details fan uBO Lite, en skeakelje Brûkersscripts tastean (ek wol oanjûn as ‘Net-ferifiearre scripts fan tredden’) yn.", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Wizigingslochboek", "description": "" @@ -255,6 +279,22 @@ "message": "Navigaasje nei potinsjeel net-winske websites wurdt blokkearre, en jo krije de opsje om troch te gean.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Pop-upblokkearring ynskeakelje", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Wannear aktyf, slute oerienkommende filters automatysk net-winske browserljepblêden dy’t troch websites oanmakke binne.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Sandbox foar it oanmeitsjen fan filters", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "Om kosmetyske of scriptletfilters fan de sandbox út ta te passen, moatte jo uBO Lite tastimming jaan foar it útfieren fan brûkersscripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Untwikkelersmodus", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/gl/messages.json b/platform/mv3/extension/_locales/gl/messages.json index 0d6a94964a697..ab74ce0fe139f 100644 --- a/platform/mv3/extension/_locales/gl/messages.json +++ b/platform/mv3/extension/_locales/gl/messages.json @@ -35,6 +35,10 @@ "message": "Política de privacidade", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Documentation", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "modo de filtrado", "description": "Label in the popup panel for the current filtering mode" @@ -87,6 +91,22 @@ "message": "Rexións, linguas", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Imported lists", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Add filter list…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL of the filter list to add", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Importar/Exportar", "description": "Text label heading the import/export area of custom filters" @@ -95,6 +115,10 @@ "message": "Pega aquí os filtros cosméticos a engadir", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Open your browser's extensions page (chrome://extensions in Chrome or about:addons in Firefox), open uBO Lite details, and toggle on Allow user scripts (also referred to as “unverified third-party scripts”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Rexistro de cambios", "description": "" @@ -255,6 +279,22 @@ "message": "Vaise bloquear a navegación en webs potencialmente non desexables, e ofrecerase a opción de bloquealas.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Enable pop-up blocking", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "When active, matching filters will automatically close unwanted browser tabs created by websites.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Filter-creation sandbox", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Modo desenvolvemento", "description": "Label for a checkbox in the options page" @@ -316,7 +356,7 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Entrar no modo eliminador de elementos", + "message": "Eliminar un elemento", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { diff --git a/platform/mv3/extension/_locales/gu/messages.json b/platform/mv3/extension/_locales/gu/messages.json index 881b780e38fa2..761ef5fa2df75 100644 --- a/platform/mv3/extension/_locales/gu/messages.json +++ b/platform/mv3/extension/_locales/gu/messages.json @@ -4,419 +4,459 @@ "description": "extension name." }, "extShortDesc": { - "message": "An efficient content blocker. Blocks ads, trackers, miners, and more immediately upon installation.", + "message": "એક કાર્યક્ષમ સામગ્રી અવરોધક. ઇન્સ્ટોલેશન પર તરત જ જાહેરાતો, ટ્રૅકર્સ, માઇનર્સ અને વધુને અવરોધિત કરે છે.", "description": "this will be in the Chrome web store: must be 132 characters or less" }, "perRulesetStats": { - "message": "{{ruleCount}} rules, converted from {{filterCount}} network filters", + "message": "{{ruleCount}} નિયમો, {{filterCount}} નેટવર્ક ફિલ્ટરોમાંથી રૂપાંતરિત", "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "dashboardName": { - "message": "uBO Lite — Dashboard", + "message": "uBO Lite — ડેશબોર્ડ", "description": "English: uBO Lite — Dashboard" }, "settingsPageName": { - "message": "Settings", + "message": "સેટિંગ્સ", "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "Custom filters", + "message": "કસ્ટમ ફિલ્ટરો", "description": "appears as tab name in dashboard" }, "developPageName": { - "message": "Develop", + "message": "વિકસાવો", "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { - "message": "About", + "message": "વિશે", "description": "appears as tab name in dashboard" }, "aboutPrivacyPolicy": { - "message": "Privacy policy", + "message": "ગોપનીયતા નીતિ", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "દસ્તાવેજીકરણ", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { - "message": "filtering mode", + "message": "ફિલ્ટરિંગ મોડ", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "On this website", + "message": "આ વેબસાઇટ પર", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "Report an issue", + "message": "સમસ્યાની જાણ કરો", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { - "message": "Open the dashboard", + "message": "ડેશબોર્ડ ખોલો", "description": "English: Click to open the dashboard" }, "popupMoreButton": { - "message": "More", + "message": "વધુ", "description": "Label to be used to show popup panel sections" }, "popupLessButton": { - "message": "Less", + "message": "ઓછું", "description": "Label to be used to hide popup panel sections" }, "3pGroupDefault": { - "message": "Default", + "message": "મૂળભૂત", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAds": { - "message": "Ads", + "message": "જાહેરાતો", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupPrivacy": { - "message": "Privacy", + "message": "ગોપનીયતા", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Malware protection, security", + "message": "માલવેર સુરક્ષા, સુરક્ષા", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { - "message": "Annoyances", + "message": "ઉપદ્રવો", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMisc": { - "message": "Miscellaneous", + "message": "વિવિધ", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupRegions": { - "message": "Regions, languages", + "message": "પ્રદેશો, ભાષાઓ", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "3pGroupImported": { + "message": "આયાત કરેલ યાદીઓ", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "customListImportLabel": { + "message": "ફિલ્ટર યાદી ઉમેરો…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "ઉમેરવા માટે ફિલ્ટર યાદીનો URL", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { - "message": "Import / Export", + "message": "આયાત / નિકાસ", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "ઉમેરવા માટે ચોક્કસ કોસ્મેટિક/સ્ક્રિપ્ટલેટ ફિલ્ટરો", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "તમારા બ્રાઉઝરનું એક્સ્ટેંશન પેજ ખોલો (Chrome માં chrome://extensions અથવા Firefox માં about:addons), uBO Lite વિગતો ખોલો, અને વપરાશકર્તા સ્ક્રિપ્ટોને મંજૂરી આપો (જેને “અવેરિફાઇડ તૃતીય-પક્ષ સ્ક્રિપ્ટો” તરીકે પણ ઓળખવામાં આવે છે) ચાલુ કરો.", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { - "message": "Changelog", + "message": "ફેરફાર યાદી", "description": "" }, "aboutCode": { - "message": "Source code (GPLv3)", + "message": "સોર્સ કોડ (GPLv3)", "description": "English: Source code (GPLv3)" }, "aboutContributors": { - "message": "Contributors", + "message": "યોગદાનકર્તાઓ", "description": "English: Contributors" }, "aboutSourceCode": { - "message": "Source code", + "message": "સોર્સ કોડ", "description": "Link text to source code repo" }, "aboutTranslations": { - "message": "Translations", + "message": "અનુવાદો", "description": "Link text to translations repo" }, "aboutFilterLists": { - "message": "Filter lists", + "message": "ફિલ્ટર યાદીઓ", "description": "Link text to uBO's own filter lists repo" }, "aboutDependencies": { - "message": "External dependencies (GPLv3-compatible):", + "message": "બાહ્ય આધારો (GPLv3-સુસંગત):", "description": "Shown in the About pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "ફિલ્ટર સમસ્યાની જાણ કરો", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "ચોક્કસ વેબસાઇટ્સ સાથે ફિલ્ટર સમસ્યાઓની જાણ uBlockOrigin/uAssets ઇશ્યુ ટ્રૅકર પર કરો. GitHub ખાતું જરૂરી છે.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting information", + "message": "સમસ્યાનિવારણ માહિતી", "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "સ્વયંસેવકોને ડુપ્લિકેટ રિપોર્ટ્સથી બોજ ન પડે તે માટે, કૃપા કરીને ચકાસો કે સમસ્યા પહેલેથી જ નોંધવામાં આવી નથી. નોંધ: બટન પર ક્લિક કરવાથી પેજનો ઓરિજિન GitHub પર મોકલવામાં આવશે.", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "GitHub પર સમાન રિપોર્ટ્સ શોધો", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "વેબ પેજનું સરનામું:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "વેબ પેજ…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- એક એન્ટ્રી પસંદ કરો --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "જાહેરાતો અથવા જાહેરાત અવશેષો દર્શાવે છે", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "ઓવરલે અથવા અન્ય ઉપદ્રવો ધરાવે છે", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBO Lite", + "message": "uBO Lite શોધી કાઢે છે", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "ગોપનીયતા-સંબંધિત સમસ્યાઓ ધરાવે છે", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBO Lite is enabled", + "message": "uBO Lite સક્ષમ હોય ત્યારે ખામીઓ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "અનિચ્છનીય ટૅબ્સ અથવા વિન્ડોઝ ખોલે છે", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "બેડવેર, ફિશિંગ તરફ દોરી જાય છે", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "વેબ પેજને “NSFW” તરીકે લેબલ કરો (“Not Safe For Work”)", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "GitHub પર નવો રિપોર્ટ બનાવો", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { - "message": "Default filtering mode", + "message": "મૂળભૂત ફિલ્ટરિંગ મોડ", "description": "The header text for the default filtering mode section" }, "defaultFilteringModeDescription": { - "message": "The default filtering mode will be overridden by per-website filtering modes. You can adjust the filtering mode on any given website according to whichever mode works best on that website. Each mode has its advantages and disadvantages.", + "message": "મૂળભૂત ફિલ્ટરિંગ મોડને પ્રતિ-વેબસાઇટ ફિલ્ટરિંગ મોડ્સ દ્વારા ઓવરરાઇડ કરવામાં આવશે. તમે કોઈપણ વેબસાઇટ પર ફિલ્ટરિંગ મોડને તે મોડ અનુસાર સમાયોજિત કરી શકો છો જે તે વેબસાઇટ પર શ્રેષ્ઠ કામ કરે છે. દરેક મોડના તેના ફાયદા અને ગેરફાયદા છે.", "description": "This describes the default filtering mode setting" }, "filteringMode0Name": { - "message": "no filtering", + "message": "કોઈ ફિલ્ટરિંગ નથી", "description": "Name of blocking mode 0" }, "filteringMode1Name": { - "message": "basic", + "message": "મૂળભૂત", "description": "Name of blocking mode 1" }, "filteringMode2Name": { - "message": "optimal", + "message": "શ્રેષ્ઠ", "description": "Name of blocking mode 2" }, "filteringMode3Name": { - "message": "complete", + "message": "સંપૂર્ણ", "description": "Name of blocking mode 3" }, "basicFilteringModeDescription": { - "message": "Basic network filtering from selected filter lists.\n\nDoes not require permission to read and modify data on websites.", + "message": "પસંદ કરેલ ફિલ્ટર યાદીઓમાંથી મૂળભૂત નેટવર્ક ફિલ્ટરિંગ.\n\nવેબસાઇટ્સ પર ડેટા વાંચવા અને સંશોધિત કરવાની પરવાનગીની જરૂર નથી.", "description": "This describes the 'basic' filtering mode" }, "optimalFilteringModeDescription": { - "message": "Advanced network filtering plus specific extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.", + "message": "પસંદ કરેલ ફિલ્ટર યાદીઓમાંથી અદ્યતન નેટવર્ક ફિલ્ટરિંગ ઉપરાંત ચોક્કસ વિસ્તૃત ફિલ્ટરિંગ.\n\nતમામ વેબસાઇટ્સ પર ડેટા વાંચવા અને સંશોધિત કરવા માટે વ્યાપક પરવાનગીની જરૂર છે.", "description": "This describes the 'optimal' filtering mode" }, "completeFilteringModeDescription": { - "message": "Advanced network filtering plus specific and generic extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.\n\nGeneric extended filtering may cause higher web page resources usage.", + "message": "પસંદ કરેલ ફિલ્ટર યાદીઓમાંથી અદ્યતન નેટવર્ક ફિલ્ટરિંગ ઉપરાંત ચોક્કસ અને સામાન્ય વિસ્તૃત ફિલ્ટરિંગ.\n\nતમામ વેબસાઇટ્સ પર ડેટા વાંચવા અને સંશોધિત કરવા માટે વ્યાપક પરવાનગીની જરૂર છે.\n\nસામાન્ય વિસ્તૃત ફિલ્ટરિંગ વેબ પેજ સંસાધનોના ઉપયોગમાં વધારો કરી શકે છે.", "description": "This describes the 'complete' filtering mode" }, "noFilteringModeDescription": { - "message": "List of websites for which no filtering will take place.", + "message": "જે વેબસાઇટ્સ માટે કોઈ ફિલ્ટરિંગ થશે નહીં તેની યાદી.", "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { - "message": "[hostnames only]\nexample.com\ngames.example\n...", + "message": "[ફક્ત હોસ્ટનામ]\nexample.com\ngames.example\n...", "description": "Default text for in edit field" }, "behaviorSectionLabel": { - "message": "Behavior", + "message": "વર્તન", "description": "The header text for the 'Behavior' section" }, "autoReloadLabel": { - "message": "Automatically reload page when changing filtering mode", + "message": "ફિલ્ટરિંગ મોડ બદલતી વખતે આપમેળે પેજ ફરીથી લોડ કરો", "description": "Label for a checkbox in the options page" }, "showBlockedCountLabel": { - "message": "Show the number of blocked requests on the toolbar icon", + "message": "ટૂલબાર આઇકન પર અવરોધિત વિનંતીઓની સંખ્યા બતાવો", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "Enable strict blocking", + "message": "કડક અવરોધ સક્ષમ કરો", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "સંભવિત અનિચ્છનીય સાઇટ્સ પર નેવિગેશન અવરોધિત કરવામાં આવશે, અને તમને આગળ વધવાનો વિકલ્પ આપવામાં આવશે.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "પોપ-અપ અવરોધ સક્ષમ કરો", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "સક્રિય હોય ત્યારે, મેળ ખાતા ફિલ્ટરો વેબસાઇટ્સ દ્વારા બનાવવામાં આવેલી અનિચ્છનીય બ્રાઉઝર ટૅબ્સ આપમેળે બંધ કરશે.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "ફિલ્ટર-નિર્માણ સેન્ડબોક્સ", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Developer mode", + "message": "ડેવલપર મોડ", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "તકનીકી વપરાશકર્તાઓ માટે યોગ્ય સુવિધાઓની ઍક્સેસ સક્ષમ કરે છે.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "બેકઅપ", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "તમારા કસ્ટમ સેટિંગ્સને ફાઇલમાં બેકઅપ લો, અથવા ફાઇલમાંથી તમારા કસ્ટમ સેટિંગ્સ પુનઃસ્થાપિત કરો.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "પુનઃસ્થાપન તમારી બધી વર્તમાન કસ્ટમ સેટિંગ્સને ઓવરરાઇટ કરશે.", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "Find lists", + "message": "યાદીઓ શોધો", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { - "message": "Page blocked", + "message": "પેજ અવરોધિત", "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite has prevented the following page from loading:", + "message": "uBO Lite એ નીચેના પેજને લોડ થતા અટકાવ્યું છે:", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "The page was blocked because of a matching filter in {{listname}}.", + "message": "{{listname}} માં મેળ ખાતા ફિલ્ટરને કારણે પેજ અવરોધિત કરવામાં આવ્યું હતું.", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "અવરોધિત પેજ બીજી સાઇટ પર રીડાયરેક્ટ કરવા માંગે છે. જો તમે આગળ વધવાનું પસંદ કરો છો, તો તમે સીધા અહીં નેવિગેટ કરશો: {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { - "message": "without parameters", + "message": "પરિમાણો વિના", "description": "Label to be used for the parameter-less URL" }, "strictblockBack": { - "message": "Go back", + "message": "પાછા જાઓ", "description": "A button to go back to the previous web page" }, "strictblockClose": { - "message": "Close this window", + "message": "આ વિન્ડો બંધ કરો", "description": "A button to close the current tab" }, "strictblockDontWarn": { - "message": "Don't warn me again about this site", + "message": "મને આ સાઇટ વિશે ફરીથી ચેતવણી આપશો નહીં", "description": "Label for checkbox in document-blocked page" }, "strictblockProceed": { - "message": "Proceed", + "message": "આગળ વધો", "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Remove an element", + "message": "તત્વ દૂર કરો", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Exit element zapper mode", + "message": "તત્વ ઝેપર મોડમાંથી બહાર નીકળો", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "કસ્ટમ ફિલ્ટર બનાવો", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "કસ્ટમ ફિલ્ટર દૂર કરો", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { - "message": "View:", + "message": "જુઓ:", "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "ફિલ્ટરિંગ મોડ વિગતો", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "કસ્ટમ DNR નિયમો", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "ના DNR નિયમો …", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "ડાયનેમિક નિયમસમૂહ", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "સત્ર નિયમસમૂહ", "description": "An option in a dropdown list" }, "saveButton": { - "message": "Save", + "message": "સાચવો", "description": "Text for buttons used to save changes" }, "revertButton": { - "message": "Revert", + "message": "પૂર્વવત્ કરો", "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "Add", + "message": "ઉમેરો", "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Import and append…", + "message": "આયાત કરો અને ઉમેરો…", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Export…", + "message": "નિકાસ કરો…", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "બેકઅપ લો…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "પુનઃસ્થાપિત કરો…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "મૂળભૂત સેટિંગ્સમાં રીસેટ કરો…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "તમારી બધી કસ્ટમ સેટિંગ્સ દૂર કરવામાં આવશે. શું તમે ખરેખર મૂળભૂત સેટિંગ્સમાં રીસેટ કરવા માંગો છો?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "અવિશ્વસનીય સ્ત્રોતોમાંથી સામગ્રી ઉમેરશો નહીં", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "નોંધાયેલ નિયમોની સંખ્યા: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "શ્રેષ્ઠ મેચ પસંદ કરવા સ્લાઇડર ખસેડો", "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Pick", + "message": "પસંદ કરો", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "પૂર્વદર્શન", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "બનાવો", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "વેબ પેજમાં મેળ ખાતા તત્વોને હાઇલાઇટ કરવા નીચે ફિલ્ટર પસંદ કરો. ફિલ્ટર દૂર કરવા કચરાપેટી પર ક્લિક કરો.", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/he/messages.json b/platform/mv3/extension/_locales/he/messages.json index bfe1ae3b38f15..991fb5b3d7227 100644 --- a/platform/mv3/extension/_locales/he/messages.json +++ b/platform/mv3/extension/_locales/he/messages.json @@ -35,6 +35,10 @@ "message": "מדיניות פרטיות", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Documentation", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "מצב מסנן", "description": "Label in the popup panel for the current filtering mode" @@ -87,6 +91,22 @@ "message": "אזורים, שפות", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "רשימות מיובאות", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "הוספת רשימת מסננים…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "העתיקו לכאן את ה URL של רשימת המסננים", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "יבוא / יצוא", "description": "Text label heading the import/export area of custom filters" @@ -95,6 +115,10 @@ "message": "העתיקו לכאן מסננים קוסמטים ספציפים לשם הוספה", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "פתחו את התוספים או ההרחבות בדפדפן שלכם (chrome://extensions בכרום או chrome://extensions בפיירפוקס), פתחו את הפרטים של uBO Lite, ותנו אישור לסקריפטים של משתמשים (או \"לאפשר לתסריטי צד שלישי לא מאומתים לגשת לנתונים שלך\").", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "יומן שינויים", "description": "" @@ -255,6 +279,22 @@ "message": "ניווט אפשרי לאתרים לא רצויים יחסם ותהיה אפשרות להחליט להמשיך.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "הפעלת חסימה לפתיחת חלונות", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "כאשר פעיל, מסננים תואמים יסגרו בצורה אוטומטית לשוניות שנוצרו על ידי אתרים.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "ארגז חול ליצירת מסננים", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "מצב מפתחים", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/hi/messages.json b/platform/mv3/extension/_locales/hi/messages.json index cec60fb8befd4..9f2c0abdb6ce8 100644 --- a/platform/mv3/extension/_locales/hi/messages.json +++ b/platform/mv3/extension/_locales/hi/messages.json @@ -20,7 +20,7 @@ "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "Custom filters", + "message": "निर्मित फ़िल्टर", "description": "appears as tab name in dashboard" }, "developPageName": { @@ -35,6 +35,10 @@ "message": "गोपनीयता नीति", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "प्रलेखन", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "फ़िल्टरिंग मोड", "description": "Label in the popup panel for the current filtering mode" @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "मैलवेयर डोमेन", + "message": "मैलवेयर सुरक्षा, सिक्योरिटी", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,14 +91,34 @@ "message": "क्षेत्र, भाषाएँ", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "आयातित सूचियाँ", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "फ़िल्टर सूची जोड़ें…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "जोड़ने के लिए फ़िल्टर सूची का URL", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { - "message": "Import / Export", + "message": "आयात / निर्यात", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "जोड़ने के लिए विशिष्ट कॉस्मेटिक/स्क्रिप्टलेट फ़िल्टर", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "अपने ब्राउज़र का एक्सटेंशन पेज खोलें (Chrome में chrome://extensions या Firefox में about:addons), uBO Lite विवरण खोलें, और उपयोगकर्ता स्क्रिप्ट की अनुमति दें (जिसे \"असत्यापित तृतीय-पक्ष स्क्रिप्ट\" भी कहा जाता है) को चालू करें।", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "परिवर्तन पत्र", "description": "" @@ -136,7 +160,7 @@ "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "डुप्लिकेट रिपोर्टों से स्वयंसेवकों पर बोझ न डालने के लिए, कृपया सत्यापित करें कि समस्या की पहले से रिपोर्ट नहीं की गई है। नोट: बटन पर क्लिक करने से पृष्ठ का मूल (origin) GitHub को भेजा जाएगा।", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { @@ -184,11 +208,11 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "वेब पृष्ठ को “NSFW” (“कार्य के लिए सुरक्षित नहीं”) के रूप में लेबल करें", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "GitHub पर नई रिपोर्ट बनाएं", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { @@ -248,43 +272,59 @@ "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "Enable strict blocking", + "message": "सख्त ब्लॉकिंग सक्षम करें", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "संभावित अवांछनीय साइटों पर नेविगेशन ब्लॉक कर दिया जाएगा, और आपको आगे बढ़ने का विकल्प दिया जाएगा।", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "पॉप-अप ब्लॉकिंग सक्षम करें", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "सक्रिय होने पर, मिलान फ़िल्टर वेबसाइटों द्वारा बनाए गए अवांछित ब्राउज़र टैब को स्वचालित रूप से बंद कर देंगे।", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "फ़िल्टर-निर्माण सैंडबॉक्स", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Developer mode", + "message": "डेवलपर मोड", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "तकनीकी उपयोगकर्ताओं के लिए उपयुक्त सुविधाओं तक पहुंच सक्षम करता है।", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "बैकअप", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "अपनी कस्टम सेटिंग्स को फ़ाइल में बैकअप करें, या फ़ाइल से अपनी कस्टम सेटिंग्स पुनर्स्थापित करें।", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "पुनर्स्थापना आपकी सभी वर्तमान कस्टम सेटिंग्स को अधिलेखित कर देगी।", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "Find lists", + "message": "सूचियाँ खोजें", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { - "message": "Page blocked", + "message": "पृष्ठ ब्लॉक किया गया", "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite has prevented the following page from loading:", + "message": "uBO लाईट ने इस पेज को लोड होने से रोक दिया हैं:", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { @@ -296,39 +336,39 @@ "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { - "message": "without parameters", + "message": "पैरामीटर के बिना", "description": "Label to be used for the parameter-less URL" }, "strictblockBack": { - "message": "Go back", + "message": "पीछे जाएं", "description": "A button to go back to the previous web page" }, "strictblockClose": { - "message": "Close this window", + "message": "इस विंडो को बंद करें", "description": "A button to close the current tab" }, "strictblockDontWarn": { - "message": "Don't warn me again about this site", + "message": "इस साइट के बारे में मुझे फिर से चेतावनी न दें", "description": "Label for checkbox in document-blocked page" }, "strictblockProceed": { - "message": "Proceed", + "message": "आगे बढ़ें", "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Remove an element", + "message": "एक तत्व हटाएँ", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Exit element zapper mode", + "message": "तत्व ज़ैपर मोड से बाहर निकलें", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "निर्मित फ़िल्टर बनाएं", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "एक कस्टम फ़िल्टर हटाएँ", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { @@ -336,23 +376,23 @@ "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "फ़िल्टरिंग मोड विवरण", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "कस्टम DNR नियम", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "के DNR नियम …", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "गतिशील नियमसेट", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "सत्र नियमसेट", "description": "An option in a dropdown list" }, "saveButton": { @@ -364,7 +404,7 @@ "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "Add", + "message": "जोड़ें", "description": "Text for buttons used to add content" }, "importAndAppendButton": { @@ -376,19 +416,19 @@ "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "बैकअप करें…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "पुनर्स्थापित करें…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "डिफ़ॉल्ट सेटिंग्स पर रीसेट करें…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "आपकी सभी कस्टम सेटिंग्स हटा दी जाएंगी। क्या आप वास्तव में डिफ़ॉल्ट सेटिंग्स पर रीसेट करना चाहते हैं?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { @@ -396,27 +436,27 @@ "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "पंजीकृत नियमों की संख्या: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "सर्वश्रेष्ठ मिलान चुनने के लिए स्लाइडर को घुमाएँ", "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Pick", + "message": "चुनें", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "पूर्वावलोकन", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "बनाएँ", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "वेब पृष्ठ में मिलान तत्वों को हाइलाइट करने के लिए नीचे एक फ़िल्टर चुनें। फ़िल्टर हटाने के लिए कूड़ेदान पर क्लिक करें।", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/hr/messages.json b/platform/mv3/extension/_locales/hr/messages.json index 1408ecea3ae7d..2c5a768911e57 100644 --- a/platform/mv3/extension/_locales/hr/messages.json +++ b/platform/mv3/extension/_locales/hr/messages.json @@ -35,6 +35,10 @@ "message": "Pravila privatnosti", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Dokumentacija", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "Način filtriranja", "description": "Label in the popup panel for the current filtering mode" @@ -87,6 +91,22 @@ "message": "Regije, jezici", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Uvezene liste", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Dodajte listu filtera…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL popisa filtera za dodavanje", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "Za primjenu kozmetičkih ili skriptlet filtera iz uvezenih popisa, morate dati uBO Lite dopuštenje za pokretanje korisničkih skripti.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Uvoz / Izvoz", "description": "Text label heading the import/export area of custom filters" @@ -95,6 +115,10 @@ "message": "Ovdje zalijepite određene vizualne filtere koje želite dodati", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Otvorite stranicu s proširenjima preglednika (chrome://extensions u Chromeu ili about:addons u Firefoxu), otvorite detalje o uBO Liteu i uključite Dopusti korisničke skripte (također se nazivaju \"nepotvrđene skripte trećih strana\").", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Popis promjena", "description": "" @@ -255,6 +279,22 @@ "message": "Navigacija do potencijalno nepoželjnih stranica bit će blokirana i bit će vam ponuđena opcija za nastavak.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Omogući blokiranje skočnih prozora", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Kada su aktivni, odgovarajući filteri automatski će zatvoriti neželjene kartice preglednika koje su kreirale web-lokacije.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Igraonica za stvaranje filtera", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "Za primjenu kozmetičkih ili skriptlet filtera iz sandboxa, morate dati uBO Lite dopuštenje za pokretanje korisničkih skripti.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Način rada za programere", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/hu/messages.json b/platform/mv3/extension/_locales/hu/messages.json index 823bdcd857679..7a9a280625f8f 100644 --- a/platform/mv3/extension/_locales/hu/messages.json +++ b/platform/mv3/extension/_locales/hu/messages.json @@ -4,7 +4,7 @@ "description": "extension name." }, "extShortDesc": { - "message": "Engedélyt nem igénylő tartalomblokkoló. A telepítés után azonnal blokkolja a hirdetéseket, nyomkövetőket, bányászokat és egyebeket.", + "message": "Egy hatékony tartalomblokkoló. A telepítés után azonnal blokkolja a hirdetéseket, nyomkövetőket, bányászokat és egyebeket.", "description": "this will be in the Chrome web store: must be 132 characters or less" }, "perRulesetStats": { @@ -35,6 +35,10 @@ "message": "Adatvédelmi irányelvek", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Dokumentáció", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "szűrési mód", "description": "Label in the popup panel for the current filtering mode" @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Malware domainek", + "message": "Kártevővédelem, biztonság", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,6 +91,22 @@ "message": "Régiók, nyelvek", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Importált listák", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Szűrőlista hozzáadása…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Illessze be ide a hozzáadandó szűrőlista webcímét", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Importálás/exportálás", "description": "Text label heading the import/export area of custom filters" @@ -95,6 +115,10 @@ "message": "Illessze be ide a hozzáadandó kozmetikai szűrőket", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Nyissa meg a böngészőkiegészítők vagy bővítmények oldalát (chrome://extensions a Chrome-ban vagy about:addons a Firefoxban), nyissa meg a uBO Lite részleteit, és kapcsolja be a Felhasználói parancsfájlok engedélyezése lehetőséget (más néven „nem ellenőrzött külső parancsfájlok”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Változások listája", "description": "" @@ -255,6 +279,22 @@ "message": "Az esetleges nem kívánatos webhelyekre való navigáció blokkolva lesz, és rákérdez arra, hogy folytatja-e.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Felugró ablakok blokkolásának engedélyezése", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Ha aktív, a megfelelő szűrők automatikusan bezárják a webhelyek által létrehozott kéretlen böngészőlapokat.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Szűrőlétrehozási homokozó", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Fejlesztői mód", "description": "Label for a checkbox in the options page" @@ -316,7 +356,7 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Belépés az elemeltávolító módba", + "message": "Elem eltávolítása", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { diff --git a/platform/mv3/extension/_locales/hy/messages.json b/platform/mv3/extension/_locales/hy/messages.json index a3a75996bf97c..41c8228a0d59b 100644 --- a/platform/mv3/extension/_locales/hy/messages.json +++ b/platform/mv3/extension/_locales/hy/messages.json @@ -20,11 +20,11 @@ "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "Custom filters", + "message": "Անհատական զտիչներ", "description": "appears as tab name in dashboard" }, "developPageName": { - "message": "Develop", + "message": "Մշակել", "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { @@ -35,12 +35,16 @@ "message": "Գաղտնիության քաղաքականություն", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Փաստաթղթավորում", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "զտման ռեժիմ", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "On this website", + "message": "Այս կայքում", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Վնասակար տիրույթներ", + "message": "Վնասակար ծրագրերից պաշտպանություն, անվտանգություն", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,14 +91,34 @@ "message": "Տարածաշրջաններ, լեզուներ", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Ներմուծված ցանկեր", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Ավելացնել զտիչների ցանկ…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Ավելացման ենթակա զտիչների ցանկի URL-ը", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { - "message": "Import / Export", + "message": "Ներմուծում / Արտահանում", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "Ավելացման ենթակա հատուկ կոսմետիկ/սկրիպտլետ զտիչներ", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Բացեք ձեր դիտարկչի ընդլայնումների էջը (chrome://extensions Chrome-ում կամ about:addons Firefox-ում), բացեք uBO Lite-ի մանրամասները և միացրեք Թույլատրել օգտատիրոջ սկրիպտները (նաև կոչվում է “չստուգված երրորդ կողմի սկրիպտներ”)։", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Փոփոխությունների մատյան", "description": "" @@ -124,27 +148,27 @@ "description": "Shown in the About pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "Հաղորդել զտիչի խնդրի մասին", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "Հաղորդել կոնկրետ կայքերի հետ կապված զտիչների խնդիրների մասին uBlockOrigin/uAssets խնդիրների հետագծման համակարգին։ Պահանջվում է GitHub հաշիվ։", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting information", + "message": "Խնդիրների լուծման տեղեկատվություն", "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "Կամավորներին կրկնվող հաղորդումներով չծանրաբեռնելու համար, խնդրում ենք ստուգել, որ խնդիրը դեռ չի հաղորդվել։ Նշում. կոճակի սեղմումը կհանգեցնի էջի ծագման (origin) ուղարկմանը GitHub։", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "Գտնել նման զեկույցներ GitHub-ում", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "Վեբ էջի հասցեն՝", "description": "Label for the URL of the page" }, "supportS6Select1": { @@ -152,43 +176,43 @@ "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- Ընտրեք տարբերակ --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "Ցուցադրում է գովազդ կամ գովազդի մնացորդներ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "Ունի ծածկույթներ կամ այլ անհարմարություններ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBO Lite", + "message": "Հայտնաբերում է uBO Lite-ը", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "Ունի գաղտնիության հետ կապված խնդիրներ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBO Lite is enabled", + "message": "Խափանվում է, երբ uBO Lite-ը միացված է", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "Բացում է անցանկալի ներդիրներ կամ պատուհաններ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "Բերում է վնասակար ծրագրերի, ֆիշինգի", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "Նշել վեբ էջը որպես “NSFW” (“Անպատշաճ աշխատանքի համար”)", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "Նոր զեկույց ստեղծել GitHub-ում", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { @@ -232,7 +256,7 @@ "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { - "message": "[hostnames only]\nexample.com\ngames.example\n...", + "message": "[միայն հոսթի անուններ]\nexample.com\ngames.example\n...", "description": "Default text for in edit field" }, "behaviorSectionLabel": { @@ -248,55 +272,71 @@ "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "Enable strict blocking", + "message": "Միացնել խիստ արգելափակումը", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "Պոտենցիալ անցանկալի կայքերի նավարկումը կարգելափակվի, և ձեզ կառաջարկվի շարունակելու հնարավորություն։", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Միացնել թռուցիկների արգելափակումը", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Ակտիվ լինելու դեպքում համապատասխան զտիչները ավտոմատ կերպով կփակեն կայքերի կողմից ստեղծված անցանկալի դիտարկչի ներդիրները։", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Զտիչների ստեղծման ավազարկղ", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Developer mode", + "message": "Մշակողի ռեժիմ", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "Միացնում է մուտքը տեխնիկական օգտատերերի համար հարմար գործառույթներին։", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "Պահուստավորում", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "Պահուստավորեք ձեր անհատական կարգավորումները ֆայլում, կամ վերականգնեք ձեր անհատական կարգավորումները ֆայլից։", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "Վերականգնումը կվերագրի ձեր բոլոր ընթացիկ անհատական կարգավորումները։", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "Find lists", + "message": "Գտնել ցանկեր", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { - "message": "Page blocked", + "message": "Էջն արգելափակված է", "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite has prevented the following page from loading:", + "message": "uBO Lite-ը կանխել է հետևյալ էջի բեռնումը՝", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "The page was blocked because of a matching filter in {{listname}}.", + "message": "Էջն արգելափակվել է {{listname}}-ում համապատասխան զտիչի պատճառով։", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "Արգելափակված էջը ցանկանում է վերահղվել մեկ այլ կայք։ Եթե ընտրեք շարունակել, դուք ուղղակիորեն կտեղափոխվեք՝ {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { - "message": "without parameters", + "message": "առանց պարամետրերի", "description": "Label to be used for the parameter-less URL" }, "strictblockBack": { @@ -308,7 +348,7 @@ "description": "A button to close the current tab" }, "strictblockDontWarn": { - "message": "Don't warn me again about this site", + "message": "Այլևս չզգուշացնել այս կայքի մասին", "description": "Label for checkbox in document-blocked page" }, "strictblockProceed": { @@ -316,107 +356,107 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Remove an element", + "message": "Հեռացնել տարրը", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Exit element zapper mode", + "message": "Ելք տարրի զապպեր ռեժիմից", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "Ստեղծել անհատական զտիչ", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "Հեռացնել անհատական զտիչը", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { - "message": "View:", + "message": "Դիտել՝", "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "Զտման ռեժիմի մանրամասներ", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "Անհատական DNR կանոններ", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "…-ի DNR կանոնները", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "Դինամիկ կանոնների հավաքածու", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "Սեսիայի կանոնների հավաքածու", "description": "An option in a dropdown list" }, "saveButton": { - "message": "Save", + "message": "Պահպանել", "description": "Text for buttons used to save changes" }, "revertButton": { - "message": "Revert", + "message": "Վերադարձնել", "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "Add", + "message": "Ավելացնել", "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Import and append…", + "message": "Ներմուծել և կցել…", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Export…", + "message": "Արտահանել…", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "Պահուստավորել…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "Վերականգնել…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "Վերակայել լռելյայն կարգավորումներին…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "Ձեր բոլոր անհատական կարգավորումները կհեռացվեն։ Դուք իսկապե՞ս ցանկանում եք վերակայել լռելյայն կարգավորումներին։", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "Մի ավելացրեք բովանդակություն անվստահելի աղբյուրներից", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "Գրանցված կանոնների քանակը՝ {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "Տեղաշարժեք սահիչը՝ լավագույն համընկնումն ընտրելու համար", "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Pick", + "message": "Ընտրել", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "Նախադիտում", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "Ստեղծել", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "Ընտրեք ներքևում գտնվող զտիչը՝ վեբ էջում համապատասխան տարրերն ընդգծելու համար։ Սեղմեք աղբարկղի պատկերակը՝ զտիչը հեռացնելու համար։", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/id/messages.json b/platform/mv3/extension/_locales/id/messages.json index e65d7b6cafc82..dc25b8c934674 100644 --- a/platform/mv3/extension/_locales/id/messages.json +++ b/platform/mv3/extension/_locales/id/messages.json @@ -35,6 +35,10 @@ "message": "Kebijakan privasi", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Documentation", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "mode filter", "description": "Label in the popup panel for the current filtering mode" @@ -87,6 +91,22 @@ "message": "Wilayah, bahasa", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Daftar yang diimpor", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Tambah daftar filter…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL filter untuk ditambahkan", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Impor / Ekspor", "description": "Text label heading the import/export area of custom filters" @@ -95,6 +115,10 @@ "message": "Tambahkan filter kosmetik dengan menempel di sini", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Open your browser's extensions page (chrome://extensions in Chrome or about:addons in Firefox), open uBO Lite details, and toggle on Allow user scripts (also referred to as “unverified third-party scripts”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Catatan perubahan", "description": "" @@ -140,7 +164,7 @@ "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Temukan laporan serupa", + "message": "Temukan laporan serupa di Github", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { @@ -188,7 +212,7 @@ "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Buat laporan baru", + "message": "Buat laporan baru di Github", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { @@ -255,6 +279,22 @@ "message": "Navigasi ke situs yang mungkin tidak diinginkan akan diblokir, dan Anda akan ditawari opsi untuk melanjutkan.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Aktifkan pemblokiran pop-up", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Saat diaktifkan, filter pencocokan akan secara otomatis menutup tab browser yang tidak diinginkan yang dibuat oleh situs web.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Lingkungan uji coba pembuatan filter", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Mode pengembang", "description": "Label for a checkbox in the options page" @@ -312,11 +352,11 @@ "description": "Label for checkbox in document-blocked page" }, "strictblockProceed": { - "message": "Proceed", + "message": "Lanjutkan", "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Masuk ke mode penghapus elemen", + "message": "Menghapus elemen", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { diff --git a/platform/mv3/extension/_locales/it/messages.json b/platform/mv3/extension/_locales/it/messages.json index 0390bcb8766a1..eea5126fb9792 100644 --- a/platform/mv3/extension/_locales/it/messages.json +++ b/platform/mv3/extension/_locales/it/messages.json @@ -4,7 +4,7 @@ "description": "extension name." }, "extShortDesc": { - "message": "Un efficiente bloccatore di contenuti. Blocca annunci, tracker, minatori e altro ancora subito dopo l'installazione.", + "message": "Un efficiente blocca-contenuti. Blocca inserzioni, tracciatori, minatori e altro ancora subito dopo l'installazione.", "description": "this will be in the Chrome web store: must be 132 characters or less" }, "perRulesetStats": { @@ -35,6 +35,10 @@ "message": "Politica di riservatezza", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Documentazione", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "Modalità di filtraggio", "description": "Label in the popup panel for the current filtering mode" @@ -44,7 +48,7 @@ "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "Segnala un problema con questo sito", + "message": "Segnala un problema", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { @@ -87,14 +91,34 @@ "message": "Lingue e regioni", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Elenchi importati", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Aggiungi elenco di filtri…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Incolla qui l'URL dell'elenco di filtri da aggiungere", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "Per applicare i filtri cosmetici o gli scriptlet provenienti da elenchi importati, è necessario concedere a uBO Lite l'autorizzazione a eseguire gli script utente.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Importa / Esporta", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Incolla qui i filtri cosmetici specifici da aggiungere", + "message": "Incolla qui i filtri cosmetici o scriptlet specifici da aggiungere.", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Apri la pagina delle estensioni del tuo browser (chrome://extensions su Chrome o about:addons su Firefox), apri i dettagli di uBO Lite e attiva l'opzione Consenti script utente (nota anche come \"script di terze parti non verificati\").", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Reg. modifiche", "description": "" @@ -255,6 +279,22 @@ "message": "La navigazione verso siti potenzialmente indesiderati verrà bloccata e ti verrà offerta la possibilità di procedere.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Abilita il blocco dei pop-up", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Quando attivo, i filtri corrispondenti chiuderanno automaticamente le schede del browser indesiderate create dai siti web.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Sandbox per la creazione di filtri", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "Per applicare i filtri cosmetici o gli scriptlet dalla sandbox, è necessario concedere a uBO Lite l'autorizzazione a eseguire gli script utente.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Modalità sviluppatore", "description": "Label for a checkbox in the options page" @@ -292,7 +332,7 @@ "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "La pagina bloccata vuole reindirizzare a un altro sito. Se scegli di procedere, navigherai direttamente su: {{url}}", + "message": "La pagina bloccata tenta di reindirizzare a un altro sito. Se scegli di procedere, navigherai direttamente verso: {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { @@ -316,7 +356,7 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Accedi alla modalità blocco rapido", + "message": "Rimuovi un elemento", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { diff --git a/platform/mv3/extension/_locales/ja/messages.json b/platform/mv3/extension/_locales/ja/messages.json index 279638fc745ca..e918a92048220 100644 --- a/platform/mv3/extension/_locales/ja/messages.json +++ b/platform/mv3/extension/_locales/ja/messages.json @@ -35,6 +35,10 @@ "message": "プライバシーポリシー", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "ドキュメント", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "フィルタリングモード", "description": "Label in the popup panel for the current filtering mode" @@ -87,14 +91,34 @@ "message": "地域・言語", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "インポートしたリスト", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "フィルターリストを追加…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "追加したいフィルターリストの URL を貼り付けてください", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "インポートしたリストの整形・スクリプトレットフィルターを適用するには、uBO Lite にユーザースクリプトの実行を許可する必要があります。", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "インポート又はエクスポート", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "ここに追加したいコスメティックフィルターをペースト", + "message": "ここに追加したい整形・スクリプトレットフィルターを貼り付け", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "ブラウザの拡張機能ページ(Chrome の場合は chrome://extensions、Firefox の場合は about:addons)を開き、uBO Lite の詳細を開いて、ユーザー スクリプトを許可する(「未検証のサードパーティ スクリプト」とも呼ばれます)をオンに切り替えてください。", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "更新履歴", "description": "" @@ -255,6 +279,22 @@ "message": "望ましくない可能性のあるサイトへのナビゲーションはブロックされ、次に進むためのオプションが表示されます。", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "ポップアップブロックを有効化", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "有効にすると、一致するフィルターはウェブサイトによって作成された不要なブラウザータブを自動的に閉じます。", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "フィルター作成サンドボックス", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "サンドボックスから整形・スクリプトレットフィルターを適用するには、uBO Lite にユーザースクリプトの実行を許可する必要があります。", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "開発者モード", "description": "Label for a checkbox in the options page" @@ -316,7 +356,7 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "要素抹消モードを開始", + "message": "要素を削除する", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { diff --git a/platform/mv3/extension/_locales/ka/messages.json b/platform/mv3/extension/_locales/ka/messages.json index 12186152d0e7e..a526c6e0b4be7 100644 --- a/platform/mv3/extension/_locales/ka/messages.json +++ b/platform/mv3/extension/_locales/ka/messages.json @@ -35,6 +35,10 @@ "message": "პირადულობის დებულება", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "ცნობარი", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "გაფილტვრის რეჟიმი", "description": "Label in the popup panel for the current filtering mode" @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "მავნე დომენები", + "message": "მავნე პროგრამებისგან დაცვა, უსაფრთხოება", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,6 +91,22 @@ "message": "მხარეები, ენები", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "შემოტანილი სიები", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "ფილტრის სიის დამატება…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "ჩასვით სიის ბმული დასამატებლად", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "გარეგნული ან სკრიპტული ფილტრების იძულებით ამოქმედებისთვის შემოტანილი სიებიდან, uBO Lite საჭიროებს მომხმარებლის სკრიპტების გაშვების ნებართვებს.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "შემოტანა / გატანა", "description": "Text label heading the import/export area of custom filters" @@ -95,6 +115,10 @@ "message": "აქ ჩასვით გარეგნული ნაწილების ცალკეული ფილტრები დასამატებლად", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "გახსენით ბრაუზერის გაფართოებების გვერდი (chrome://extensions Chrome-ში ან about:addons Firefox-ში), იხილეთ uBO Lite ვრცლად და გადართეთ მომხმარებლის სკრიპტების ნებართვა (აგრეთვე შეიძლება ეწეროს „დაუმოწმებელი გარეშე სკრიპტები“).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "ცვლილებები", "description": "" @@ -255,6 +279,22 @@ "message": "შეიზღუდა სავარაუდოდ არასასურველ გვერდებზე გადასვლა, საშუალება გეძლევათ, მაინც განაგრძოთ.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "ამომხტომების შეზღუდვის ჩართვა", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "როცა მოქმედია, შესაბამისი ფილტრები თავისით დახურავს ვებსაიტების მიერ გახსნილ არასასურველ ჩანართებს.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "ფილტრის შესაქმნელი ცალკე გარემო", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "გარეგნული ან სკრიპტული ფილტრების იძულებით ამოქმედებისთვის განცაკლევებული გარემოდან, uBO Lite საჭიროებს მომხმარებლის სკრიპტების გაშვების ნებართვებს.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "შემმუშვებლის რეჟიმი", "description": "Label for a checkbox in the options page" @@ -316,7 +356,7 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "ნაწილების ამოჭრის რეჟიმში გადასვლა", + "message": "ელემენტის წაშლა", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { diff --git a/platform/mv3/extension/_locales/kk/messages.json b/platform/mv3/extension/_locales/kk/messages.json index b53bf06bee105..3db36a5dd5932 100644 --- a/platform/mv3/extension/_locales/kk/messages.json +++ b/platform/mv3/extension/_locales/kk/messages.json @@ -35,6 +35,10 @@ "message": "Жекелік саясаты", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Құжаттама", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "сүзгілеу режимі", "description": "Label in the popup panel for the current filtering mode" @@ -87,6 +91,22 @@ "message": "Аймақтар, тілдер", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Импортталған тізімдер", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Сүзгі тізімін қосу…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Қосылатын сүзгі тізімінің URL-мекенжайы", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Импорттау / Экспорттау", "description": "Text label heading the import/export area of custom filters" @@ -95,6 +115,10 @@ "message": "Қосылатын арнайы косметикалық сүзгілерді осы жерге кірістіріңіз", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Браузеріңіздің кеңейтулер бетін ашыңыз (chrome://extensions Chrome-да немесе about:addons Firefox-та), uBO Lite мәліметтерін ашып, Пайдаланушы скрипттеріне рұқсат ету (сонымен қатар “расталмаған үшінші тарап скрипттері” деп аталады) қосқышын қосыңыз.", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Өзгерістер журналы", "description": "" @@ -255,6 +279,22 @@ "message": "Ықтимал қалаусыз сайттарға навигация блокталған болады және сізге жалғастыру опциясы ұсынылады.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Қалқымалы терезелерді блоктауды қосу", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Белсенді болған кезде, сәйкес сүзгілер веб-сайттар жасаған қажетсіз браузер қойындыларын автоматты түрде жабады.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Сүзгі құру құмсалғышы", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Әзірлеуші режимі", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/kn/messages.json b/platform/mv3/extension/_locales/kn/messages.json index 1c53367d39267..fb1ddeb69e36d 100644 --- a/platform/mv3/extension/_locales/kn/messages.json +++ b/platform/mv3/extension/_locales/kn/messages.json @@ -8,7 +8,7 @@ "description": "this will be in the Chrome web store: must be 132 characters or less" }, "perRulesetStats": { - "message": "{{ruleCount}} rules, converted from {{filterCount}} network filters", + "message": "{{ruleCount}} ನಿಯಮಗಳು, {{filterCount}} ಜಾಲ ಶೋಧಕಗಳಿಂದ ಪರಿವರ್ತಿಸಲಾಗಿದೆ", "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "dashboardName": { @@ -20,11 +20,11 @@ "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "Custom filters", + "message": "ಕಸ್ಟಮ್ ಶೋಧಕಗಳು", "description": "appears as tab name in dashboard" }, "developPageName": { - "message": "Develop", + "message": "ಅಭಿವೃದ್ಧಿಪಡಿಸು", "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { @@ -35,16 +35,20 @@ "message": "ಗೌಪ್ಯತಾ ನೀತಿ\n", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "ದಸ್ತಾವೇಜು", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "ಫಿಲ್ಟರಿಂಗ್ ಮೋಡ್", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "On this website", + "message": "ಈ ವೆಬ್ಸೈಟ್ನಲ್ಲಿ", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "Report an issue", + "message": "ಸಮಸ್ಯೆಯನ್ನು ವರದಿ ಮಾಡಿ", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { @@ -72,11 +76,11 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Malware protection, security", + "message": "ಮಾಲ್ವೇರ್ ರಕ್ಷಣೆ, ಭದ್ರತೆ", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { - "message": "Annoyances", + "message": "ಕಿರಿಕಿರಿಗಳು", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMisc": { @@ -87,24 +91,44 @@ "message": "ಪ್ರದೇಶಗಳು, ಭಾಷೆಗಳು\n", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "ಆಮದು ಮಾಡಿದ ಪಟ್ಟಿಗಳು", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "ಶೋಧಕ ಪಟ್ಟಿಯನ್ನು ಸೇರಿಸು…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "ಸೇರಿಸಬೇಕಾದ ಶೋಧಕ ಪಟ್ಟಿಯ URL", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { - "message": "Import / Export", + "message": "ಆಮದು / ರಫ್ತು", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "ಸೇರಿಸಬೇಕಾದ ನಿರ್ದಿಷ್ಟ ಸೌಂದರ್ಯ/ಸ್ಕ್ರಿಪ್ಟ್ಲೆಟ್ ಶೋಧಕಗಳು", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "ನಿಮ್ಮ ಬ್ರೌಸರ್ನ ವಿಸ್ತರಣೆಗಳ ಪುಟವನ್ನು ತೆರೆಯಿರಿ (Chrome ನಲ್ಲಿ chrome://extensions ಅಥವಾ Firefox ನಲ್ಲಿ about:addons), uBO Lite ವಿವರಗಳನ್ನು ತೆರೆಯಿರಿ, ಮತ್ತು ಬಳಕೆದಾರ ಸ್ಕ್ರಿಪ್ಟ್ಗಳನ್ನು ಅನುಮತಿಸು ಅನ್ನು ಟಾಗಲ್ ಆನ್ ಮಾಡಿ (ಇದನ್ನು “ಪರಿಶೀಲಿಸದ ಮೂರನೇ-ಪಕ್ಷ ಸ್ಕ್ರಿಪ್ಟ್ಗಳು” ಎಂದೂ ಕರೆಯಲಾಗುತ್ತದೆ).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "ಬದಲಾವಣೆಗಳು", "description": "" }, "aboutCode": { - "message": "Source code (GPLv3)", + "message": "ಮೂಲ ಕೋಡ್ (GPLv3)", "description": "English: Source code (GPLv3)" }, "aboutContributors": { - "message": "Contributors", + "message": "ಕೊಡುಗೆದಾರರು", "description": "English: Contributors" }, "aboutSourceCode": { @@ -120,87 +144,87 @@ "description": "Link text to uBO's own filter lists repo" }, "aboutDependencies": { - "message": "External dependencies (GPLv3-compatible):", + "message": "ಬಾಹ್ಯ ಅವಲಂಬನೆಗಳು (GPLv3-ಹೊಂದಾಣಿಕೆ):", "description": "Shown in the About pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "ಶೋಧಕ ಸಮಸ್ಯೆಯನ್ನು ವರದಿ ಮಾಡಿ", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "ನಿರ್ದಿಷ್ಟ ವೆಬ್ಸೈಟ್ಗಳೊಂದಿಗಿನ ಶೋಧಕ ಸಮಸ್ಯೆಗಳನ್ನು uBlockOrigin/uAssets ಸಮಸ್ಯೆ ಟ್ರ್ಯಾಕರ್ಗೆ ವರದಿ ಮಾಡಿ. GitHub ಖಾತೆಯ ಅಗತ್ಯವಿದೆ.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting information", + "message": "ಸಮಸ್ಯೆ ನಿವಾರಣೆ ಮಾಹಿತಿ", "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "ಸ್ವಯಂಸೇವಕರಿಗೆ ನಕಲು ವರದಿಗಳ ಹೊರೆಯನ್ನು ತಪ್ಪಿಸಲು, ಸಮಸ್ಯೆಯನ್ನು ಈಗಾಗಲೇ ವರದಿ ಮಾಡಿಲ್ಲವೆಂದು ದಯವಿಟ್ಟು ಪರಿಶೀಲಿಸಿ. ಸೂಚನೆ: ಬಟನ್ ಕ್ಲಿಕ್ ಮಾಡುವುದರಿಂದ ಪುಟದ ಮೂಲವನ್ನು GitHub ಗೆ ಕಳುಹಿಸಲಾಗುತ್ತದೆ.", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "GitHub ನಲ್ಲಿ ಹೋಲುವ ವರದಿಗಳನ್ನು ಹುಡುಕು", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "ವೆಬ್ ಪುಟದ ವಿಳಾಸ:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "ವೆಬ್ ಪುಟ…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- ಒಂದು ನಮೂದನ್ನು ಆಯ್ಕೆಮಾಡಿ --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "ಜಾಹೀರಾತುಗಳು ಅಥವಾ ಜಾಹೀರಾತು ಉಳಿಕೆಗಳನ್ನು ತೋರಿಸುತ್ತದೆ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "ಓವರ್ಲೇಗಳು ಅಥವಾ ಇತರ ತೊಂದರೆಗಳನ್ನು ಹೊಂದಿದೆ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBO Lite", + "message": "uBO Lite ಅನ್ನು ಪತ್ತೆ ಮಾಡುತ್ತದೆ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "ಗೌಪ್ಯತೆ-ಸಂಬಂಧಿತ ಸಮಸ್ಯೆಗಳನ್ನು ಹೊಂದಿದೆ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBO Lite is enabled", + "message": "uBO Lite ಸಕ್ರಿಯವಾಗಿರುವಾಗ ಅಸಮರ್ಪಕವಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "ಅನಪೇಕ್ಷಿತ ಟ್ಯಾಬ್ಗಳು ಅಥವಾ ವಿಂಡೋಗಳನ್ನು ತೆರೆಯುತ್ತದೆ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "ದುರುಪಯೋಗಿ ಸಾಫ್ಟ್ವೇರ್, ಫಿಶಿಂಗ್ಗೆ ಕಾರಣವಾಗುತ್ತದೆ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "ವೆಬ್ ಪುಟವನ್ನು “NSFW” ಎಂದು ಗುರುತಿಸು (“ಕೆಲಸಕ್ಕೆ ಸುರಕ್ಷಿತವಲ್ಲ”)", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "GitHub ನಲ್ಲಿ ಹೊಸ ವರದಿಯನ್ನು ರಚಿಸು", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { - "message": "Default filtering mode", + "message": "ಡೀಫಾಲ್ಟ್ ಶೋಧನಾ ವಿಧಾನ", "description": "The header text for the default filtering mode section" }, "defaultFilteringModeDescription": { - "message": "The default filtering mode will be overridden by per-website filtering modes. You can adjust the filtering mode on any given website according to whichever mode works best on that website. Each mode has its advantages and disadvantages.", + "message": "ಡೀಫಾಲ್ಟ್ ಶೋಧನಾ ವಿಧಾನವು ಪ್ರತಿ-ವೆಬ್ಸೈಟ್ ಶೋಧನಾ ವಿಧಾನಗಳಿಂದ ಅತಿಕ್ರಮಿಸಲ್ಪಡುತ್ತದೆ. ಯಾವುದೇ ವೆಬ್ಸೈಟ್ನಲ್ಲಿ ಆ ವೆಬ್ಸೈಟ್ಗೆ ಯಾವ ವಿಧಾನವು ಉತ್ತಮವಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ ಎಂಬುದರ ಆಧಾರದ ಮೇಲೆ ನೀವು ಶೋಧನಾ ವಿಧಾನವನ್ನು ಹೊಂದಿಸಬಹುದು. ಪ್ರತಿಯೊಂದು ವಿಧಾನವು ತನ್ನದೇ ಆದ ಅನುಕೂಲಗಳು ಮತ್ತು ಅನಾನುಕೂಲಗಳನ್ನು ಹೊಂದಿದೆ.", "description": "This describes the default filtering mode setting" }, "filteringMode0Name": { - "message": "no filtering", + "message": "ಶೋಧನೆ ಇಲ್ಲ", "description": "Name of blocking mode 0" }, "filteringMode1Name": { @@ -216,23 +240,23 @@ "description": "Name of blocking mode 3" }, "basicFilteringModeDescription": { - "message": "Basic network filtering from selected filter lists.\n\nDoes not require permission to read and modify data on websites.", + "message": "ಆಯ್ಕೆಮಾಡಿದ ಶೋಧಕ ಪಟ್ಟಿಗಳಿಂದ ಮೂಲ ಜಾಲ ಶೋಧನೆ.\n\nವೆಬ್ಸೈಟ್ಗಳಲ್ಲಿ ದತ್ತಾಂಶವನ್ನು ಓದಲು ಮತ್ತು ಮಾರ್ಪಡಿಸಲು ಅನುಮತಿಯ ಅಗತ್ಯವಿಲ್ಲ.", "description": "This describes the 'basic' filtering mode" }, "optimalFilteringModeDescription": { - "message": "Advanced network filtering plus specific extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.", + "message": "ಆಯ್ಕೆಮಾಡಿದ ಶೋಧಕ ಪಟ್ಟಿಗಳಿಂದ ಸುಧಾರಿತ ಜಾಲ ಶೋಧನೆ ಜೊತೆಗೆ ನಿರ್ದಿಷ್ಟ ವಿಸ್ತೃತ ಶೋಧನೆ.\n\nಎಲ್ಲಾ ವೆಬ್ಸೈಟ್ಗಳಲ್ಲಿ ದತ್ತಾಂಶವನ್ನು ಓದಲು ಮತ್ತು ಮಾರ್ಪಡಿಸಲು ವ್ಯಾಪಕ ಅನುಮತಿಯ ಅಗತ್ಯವಿದೆ.", "description": "This describes the 'optimal' filtering mode" }, "completeFilteringModeDescription": { - "message": "Advanced network filtering plus specific and generic extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.\n\nGeneric extended filtering may cause higher web page resources usage.", + "message": "ಆಯ್ಕೆಮಾಡಿದ ಶೋಧಕ ಪಟ್ಟಿಗಳಿಂದ ಸುಧಾರಿತ ಜಾಲ ಶೋಧನೆ ಜೊತೆಗೆ ನಿರ್ದಿಷ್ಟ ಮತ್ತು ಸಾಮಾನ್ಯ ವಿಸ್ತೃತ ಶೋಧನೆ.\n\nಎಲ್ಲಾ ವೆಬ್ಸೈಟ್ಗಳಲ್ಲಿ ದತ್ತಾಂಶವನ್ನು ಓದಲು ಮತ್ತು ಮಾರ್ಪಡಿಸಲು ವ್ಯಾಪಕ ಅನುಮತಿಯ ಅಗತ್ಯವಿದೆ.\n\nಸಾಮಾನ್ಯ ವಿಸ್ತೃತ ಶೋಧನೆಯು ಹೆಚ್ಚಿನ ವೆಬ್ ಪುಟ ಸಂಪನ್ಮೂಲಗಳ ಬಳಕೆಗೆ ಕಾರಣವಾಗಬಹುದು.", "description": "This describes the 'complete' filtering mode" }, "noFilteringModeDescription": { - "message": "List of websites for which no filtering will take place.", + "message": "ಯಾವುದೇ ಶೋಧನೆ ನಡೆಯದ ವೆಬ್ಸೈಟ್ಗಳ ಪಟ್ಟಿ.", "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { - "message": "[hostnames only]\nexample.com\ngames.example\n...", + "message": "[ಹೋಸ್ಟ್ಹೆಸರುಗಳು ಮಾತ್ರ]\nexample.com\ngames.example\n...", "description": "Default text for in edit field" }, "behaviorSectionLabel": { @@ -240,183 +264,199 @@ "description": "The header text for the 'Behavior' section" }, "autoReloadLabel": { - "message": "Automatically reload page when changing filtering mode", + "message": "ಶೋಧನಾ ವಿಧಾನವನ್ನು ಬದಲಾಯಿಸುವಾಗ ಪುಟವನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಮರುಲೋಡ್ ಮಾಡು", "description": "Label for a checkbox in the options page" }, "showBlockedCountLabel": { - "message": "Show the number of blocked requests on the toolbar icon", + "message": "ಪರಿಕರಪಟ್ಟಿ ಐಕಾನ್ನಲ್ಲಿ ನಿರ್ಬಂಧಿಸಿದ ವಿನಂತಿಗಳ ಸಂಖ್ಯೆಯನ್ನು ತೋರಿಸು", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "Enable strict blocking", + "message": "ಕಟ್ಟುನಿಟ್ಟಿನ ನಿರ್ಬಂಧವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸು", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "ಸಂಭಾವ್ಯ ಅನಪೇಕ್ಷಿತ ಸೈಟ್ಗಳಿಗೆ ನ್ಯಾವಿಗೇಶನ್ ಅನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗುತ್ತದೆ, ಮತ್ತು ನಿಮಗೆ ಮುಂದುವರಿಯುವ ಆಯ್ಕೆಯನ್ನು ನೀಡಲಾಗುತ್ತದೆ.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "ಪಾಪ್-ಅಪ್ ನಿರ್ಬಂಧವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸು", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "ಸಕ್ರಿಯವಾಗಿದ್ದಾಗ, ಹೊಂದಾಣಿಕೆಯ ಶೋಧಕಗಳು ವೆಬ್ಸೈಟ್ಗಳಿಂದ ರಚಿಸಲಾದ ಅನಪೇಕ್ಷಿತ ಬ್ರೌಸರ್ ಟ್ಯಾಬ್ಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಮುಚ್ಚುತ್ತವೆ.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "ಶೋಧಕ-ರಚನೆ ಸ್ಯಾಂಡ್ಬಾಕ್ಸ್", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Developer mode", + "message": "ಡೆವಲಪರ್ ಮೋಡ್", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "ತಾಂತ್ರಿಕ ಬಳಕೆದಾರರಿಗೆ ಸೂಕ್ತವಾದ ವೈಶಿಷ್ಟ್ಯಗಳಿಗೆ ಪ್ರವೇಶವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "ಬ್ಯಾಕಪ್", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "ನಿಮ್ಮ ಕಸ್ಟಮ್ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಫೈಲ್ಗೆ ಬ್ಯಾಕಪ್ ಮಾಡಿ, ಅಥವಾ ನಿಮ್ಮ ಕಸ್ಟಮ್ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಫೈಲ್ನಿಂದ ಮರುಸ್ಥಾಪಿಸಿ.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "ಮರುಸ್ಥಾಪಿಸುವುದು ನಿಮ್ಮ ಎಲ್ಲಾ ಪ್ರಸ್ತುತ ಕಸ್ಟಮ್ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಅತಿಕ್ರಮಿಸುತ್ತದೆ.", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "Find lists", + "message": "ಪಟ್ಟಿಗಳನ್ನು ಹುಡುಕು", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { - "message": "Page blocked", + "message": "ಪುಟ ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ", "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite has prevented the following page from loading:", + "message": "uBO Lite ಈ ಕೆಳಗಿನ ಪುಟವನ್ನು ಲೋಡ್ ಆಗದಂತೆ ತಡೆದಿದೆ:", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "The page was blocked because of a matching filter in {{listname}}.", + "message": "{{listname}} ನಲ್ಲಿ ಹೊಂದಾಣಿಕೆಯ ಶೋಧಕದ ಕಾರಣದಿಂದ ಪುಟವನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ.", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "ನಿರ್ಬಂಧಿಸಿದ ಪುಟವು ಇನ್ನೊಂದು ಸೈಟ್ಗೆ ಮರುನಿರ್ದೇಶಿಸಲು ಬಯಸುತ್ತದೆ. ನೀವು ಮುಂದುವರಿಯಲು ಆರಿಸಿದರೆ, ನೀವು ನೇರವಾಗಿ ಇಲ್ಲಿಗೆ ನ್ಯಾವಿಗೇಟ್ ಮಾಡುತ್ತೀರಿ: {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { - "message": "without parameters", + "message": "ನಿಯತಾಂಕಗಳಿಲ್ಲದೆ", "description": "Label to be used for the parameter-less URL" }, "strictblockBack": { - "message": "Go back", + "message": "ಹಿಂದೆ ಹೋಗು", "description": "A button to go back to the previous web page" }, "strictblockClose": { - "message": "Close this window", + "message": "ಈ ವಿಂಡೋವನ್ನು ಮುಚ್ಚು", "description": "A button to close the current tab" }, "strictblockDontWarn": { - "message": "Don't warn me again about this site", + "message": "ಈ ಸೈಟ್ ಬಗ್ಗೆ ಮತ್ತೆ ಎಚ್ಚರಿಸಬೇಡಿ", "description": "Label for checkbox in document-blocked page" }, "strictblockProceed": { - "message": "Proceed", + "message": "ಮುಂದುವರಿಯಿರಿ", "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Remove an element", + "message": "ಅಂಶವನ್ನು ತೆಗೆದುಹಾಕು", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Exit element zapper mode", + "message": "ಎಲಿಮೆಂಟ್ ಜಾಪರ್ ಮೋಡ್ನಿಂದ ನಿರ್ಗಮಿಸು", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "ಕಸ್ಟಮ್ ಶೋಧಕವನ್ನು ರಚಿಸು", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "ಕಸ್ಟಮ್ ಶೋಧಕವನ್ನು ತೆಗೆದುಹಾಕು", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { - "message": "View:", + "message": "ವೀಕ್ಷಿಸು:", "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "ಶೋಧನಾ ವಿಧಾನದ ವಿವರಗಳು", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "ಕಸ್ಟಮ್ DNR ನಿಯಮಗಳು", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "… ನ DNR ನಿಯಮಗಳು", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "ಕ್ರಿಯಾತ್ಮಕ ನಿಯಮಗಳ ಗುಂಪು", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "ಅಧಿವೇಶನ ನಿಯಮಗಳ ಗುಂಪು", "description": "An option in a dropdown list" }, "saveButton": { - "message": "Save", + "message": "ಉಳಿಸು", "description": "Text for buttons used to save changes" }, "revertButton": { - "message": "Revert", + "message": "ಹಿಂದಿರುಗಿಸು", "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "Add", + "message": "ಸೇರಿಸು", "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Import and append…", + "message": "ಆಮದು ಮಾಡಿ ಮತ್ತು ಸೇರಿಸು…", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Export…", + "message": "ರಫ್ತು ಮಾಡು…", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "ಬ್ಯಾಕಪ್ ಮಾಡು…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "ಮರುಸ್ಥಾಪಿಸು…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "ಡೀಫಾಲ್ಟ್ ಸೆಟ್ಟಿಂಗ್ಗಳಿಗೆ ಮರುಹೊಂದಿಸು…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "ನಿಮ್ಮ ಎಲ್ಲಾ ಕಸ್ಟಮ್ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ತೆಗೆದುಹಾಕಲಾಗುವುದು. ನೀವು ನಿಜವಾಗಿಯೂ ಡೀಫಾಲ್ಟ್ ಸೆಟ್ಟಿಂಗ್ಗಳಿಗೆ ಮರುಹೊಂದಿಸಲು ಬಯಸುವಿರಾ?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "ಅವಿಶ್ವಾಸಾರ್ಹ ಮೂಲಗಳಿಂದ ವಿಷಯವನ್ನು ಸೇರಿಸಬೇಡಿ", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "ನೋಂದಾಯಿತ ನಿಯಮಗಳ ಸಂಖ್ಯೆ: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "ಉತ್ತಮ ಹೊಂದಾಣಿಕೆಯನ್ನು ಆಯ್ಕೆ ಮಾಡಲು ಸ್ಲೈಡರ್ ಅನ್ನು ಸರಿಸು", "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Pick", + "message": "ಆಯ್ಕೆಮಾಡು", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "ಮುನ್ನೋಟ", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "ರಚಿಸು", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "ವೆಬ್ ಪುಟದಲ್ಲಿ ಹೊಂದಾಣಿಕೆಯ ಅಂಶಗಳನ್ನು ಹೈಲೈಟ್ ಮಾಡಲು ಕೆಳಗಿನ ಶೋಧಕವನ್ನು ಆಯ್ಕೆಮಾಡಿ. ಶೋಧಕವನ್ನು ತೆಗೆದುಹಾಕಲು ಕಸದ ಬುಟ್ಟಿಯ ಮೇಲೆ ಕ್ಲಿಕ್ ಮಾಡಿ.", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/ko/messages.json b/platform/mv3/extension/_locales/ko/messages.json index b2c1b8b24988f..3f389cad19c5a 100644 --- a/platform/mv3/extension/_locales/ko/messages.json +++ b/platform/mv3/extension/_locales/ko/messages.json @@ -35,16 +35,20 @@ "message": "개인정보 처리방침", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "문서", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "필터링 모드", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "이 웹사이트에서는", + "message": "이 웹사이트에서", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "이 사이트의 이슈를 신고하기", + "message": "이슈 신고하기", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { @@ -60,7 +64,7 @@ "description": "Label to be used to hide popup panel sections" }, "3pGroupDefault": { - "message": "기본값", + "message": "기본", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAds": { @@ -87,14 +91,34 @@ "message": "지역, 언어", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "가져온 목록", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "필터 목록 추가…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "추가하려는 필터 목록의 URL 입력", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "가져온 목록의 요소 숨김 및 스크립트 주입 필터를 적용하려면 uBO Lite에 사용자 스크립트 실행 권한을 허용해야 합니다.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "가져오기 / 내보내기", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "여기에 추가하려는 요소 숨김 필터 붙여넣기", + "message": "추가하려는 요소 숨김 또는 스크립트 주입 필터 입력", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "브라우저의 확장 프로그램 페이지(Chrome chrome://extensions, Firefox는 about:addons)를 열고, uBO Lite 세부 정보를 연 뒤, 사용자 스크립트 허용(혹은 \"검증되지 않은 타사 스크립트 허용\")을 활성화하세요.", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "변경 로그", "description": "" @@ -152,7 +176,7 @@ "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- 주제 선택 --", + "message": "-- 항목 선택 --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { @@ -160,7 +184,7 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "오버레이나 기타 성가신 요소를 보여줍니다", + "message": "오버레이나 기타 방해 요소를 보여줍니다", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { @@ -172,7 +196,7 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "uBO Lite를 켜면 오작동합니다", + "message": "uBO Lite가 활성화되어 있을 때 오작동합니다", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { @@ -180,7 +204,7 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "악성코드, 피싱으로 유도합니다", + "message": "악성 소프트웨어, 피싱으로 유도합니다", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { @@ -240,7 +264,7 @@ "description": "The header text for the 'Behavior' section" }, "autoReloadLabel": { - "message": "필터링 모드를 변경할 때 페이지 자동 새로고침", + "message": "필터링 모드 변경 시 페이지 자동 새로고침", "description": "Label for a checkbox in the options page" }, "showBlockedCountLabel": { @@ -255,6 +279,22 @@ "message": "잠재적으로 유해할 수 있는 사이트로의 접속이 차단되며, 계속 진행할지 여부를 선택할 수 있는 옵션이 제공됩니다.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "팝업 차단 활성화", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "활성화되면, 일치하는 필터가 웹사이트에서 열린 원치 않는 브라우저 탭을 자동으로 닫습니다.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "필터 제작용 샌드박스", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "샌드박스 요소 숨김 및 스크립트 주입 필터를 적용하려면 uBO Lite에 사용자 스크립트 실행 권한을 허용해야 합니다.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "개발자 모드", "description": "Label for a checkbox in the options page" @@ -276,7 +316,7 @@ "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "목록 찾기", + "message": "목록 검색", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { @@ -284,7 +324,7 @@ "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite가 다음 페이지를 불러오지 못하게 했습니다.", + "message": "uBO Lite가 다음 페이지를 불러오지 못하도록 차단했습니다:", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { @@ -292,7 +332,7 @@ "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "차단된 페이지에서 다른 사이트로 이동하려 합니다. 계속하시면, {{url}} 주소로 바로 이동합니다.", + "message": "차단된 페이지가 다른 사이트로 리다이렉션하려 합니다. 계속 진행하기로 선택하면 다음 주소로 바로 이동합니다: {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { @@ -300,7 +340,7 @@ "description": "Label to be used for the parameter-less URL" }, "strictblockBack": { - "message": "뒤로", + "message": "뒤로 이동", "description": "A button to go back to the previous web page" }, "strictblockClose": { @@ -316,11 +356,11 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "숨길 요소 선택하기", + "message": "요소 제거하기", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "숨길 요소 선택 종료하기", + "message": "요소 제거 모드 종료", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { @@ -336,7 +376,7 @@ "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "필터링 모드 상세정보", + "message": "필터링 모드 상세 정보", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { @@ -392,7 +432,7 @@ "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "신뢰할 수 없는 출처의 콘텐츠를 추가하지 마십시오", + "message": "신뢰할 수 없는 출처의 콘텐츠는 추가하지 마세요", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { diff --git a/platform/mv3/extension/_locales/lt/messages.json b/platform/mv3/extension/_locales/lt/messages.json index 4deafc2a3b24f..204119217a100 100644 --- a/platform/mv3/extension/_locales/lt/messages.json +++ b/platform/mv3/extension/_locales/lt/messages.json @@ -4,11 +4,11 @@ "description": "extension name." }, "extShortDesc": { - "message": "An efficient content blocker. Blocks ads, trackers, miners, and more immediately upon installation.", + "message": "Veiksmingas turinio blokatorius. Iškart po įdiegimo blokuoja skelbimus, sekimo priemones, kriptovaliutų kasėjus ir dar daugiau.", "description": "this will be in the Chrome web store: must be 132 characters or less" }, "perRulesetStats": { - "message": "{{ruleCount}} rules, converted from {{filterCount}} network filters", + "message": "{{ruleCount}} taisyklės, konvertuotos iš {{filterCount}} tinklo filtrų", "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "dashboardName": { @@ -20,11 +20,11 @@ "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "Custom filters", + "message": "Pasirinktiniai filtrai", "description": "appears as tab name in dashboard" }, "developPageName": { - "message": "Develop", + "message": "Kūrimas", "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { @@ -35,20 +35,24 @@ "message": "Privatumo politika", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Dokumentacija", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { - "message": "filtering mode", + "message": "filtravimo režimas", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "On this website", + "message": "Šioje svetainėje", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "Report an issue", + "message": "Pranešti apie problemą", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { - "message": "Open the dashboard", + "message": "Atidaryti skydelį", "description": "English: Click to open the dashboard" }, "popupMoreButton": { @@ -60,7 +64,7 @@ "description": "Label to be used to hide popup panel sections" }, "3pGroupDefault": { - "message": "Default", + "message": "Numatytasis", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAds": { @@ -72,39 +76,59 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Malware protection, security", + "message": "Apsauga nuo kenkėjiškų programų, saugumas", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { - "message": "Annoyances", + "message": "Erzinimai", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMisc": { - "message": "Miscellaneous", + "message": "Įvairūs", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupRegions": { "message": "Regionai, kalbos", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Importuoti sąrašai", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Pridėti filtrų sąrašą…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Pridedamo filtrų sąrašo URL", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { - "message": "Import / Export", + "message": "Importuoti / Eksportuoti", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "Konkretūs kosmetiniai / scenarijų filtrai, kuriuos norite pridėti", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Atidarykite naršyklės plėtinių puslapį (chrome://extensions sistemoje Chrome arba about:addons sistemoje Firefox), atidarykite uBO Lite išsamią informaciją ir įjunkite Leisti vartotojo scenarijus (taip pat vadinama „nepatikrintais trečiųjų šalių scenarijais“).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Pakeitimų žurnalas", "description": "" }, "aboutCode": { - "message": "Source code (GPLv3)", + "message": "Šaltinio kodas (GPLv3)", "description": "English: Source code (GPLv3)" }, "aboutContributors": { - "message": "Contributors", + "message": "Autoriai", "description": "English: Contributors" }, "aboutSourceCode": { @@ -124,115 +148,115 @@ "description": "Shown in the About pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "Pranešti apie filtro problemą", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "Praneškite apie filtrų problemas su konkrečiomis svetainėmis uBlockOrigin/uAssets problemų sekimo sistemoje. Reikia GitHub paskyros.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting information", + "message": "Triktčių šalinimo informacija", "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "Kad neapkrautumėte savanorių dubliavimosi pranešimais, patikrinkite, ar ši problema jau nebuvo pranešta. Pastaba: paspaudus mygtuką, puslapio kilmė bus išsiųsta į GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "Rasti panašius pranešimus GitHub", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "Tinklalapio adresas:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "Tinklalapis…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- Pasirinkite įrašą --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "Rodo skelbimus arba skelbimų likučius", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "Turi perdangas ar kitus trukdžius", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBO Lite", + "message": "Aptinka uBO Lite", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "Turi su privatumu susijusių problemų", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBO Lite is enabled", + "message": "Veikia netinkamai, kai įjungtas uBO Lite", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "Atidaro nepageidaujamas korteles ar langus", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "Veda prie kenkėjiškų programų, sukčiavimo (phishing)", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "Pažymėti tinklalapį kaip „NSFW“ („Netinkama darbui“)", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "Sukurti naują pranešimą GitHub", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { - "message": "Default filtering mode", + "message": "Numatytasis filtravimo režimas", "description": "The header text for the default filtering mode section" }, "defaultFilteringModeDescription": { - "message": "The default filtering mode will be overridden by per-website filtering modes. You can adjust the filtering mode on any given website according to whichever mode works best on that website. Each mode has its advantages and disadvantages.", + "message": "Numatytąjį filtravimo režimą pakeis filtravimo režimai, nustatyti atskiroms svetainėms. Galite koreguoti filtravimo režimą bet kurioje svetainėje pagal tai, kuris režimas joje veikia geriausiai. Kiekvienas režimas turi savo privalumų ir trūkumų.", "description": "This describes the default filtering mode setting" }, "filteringMode0Name": { - "message": "no filtering", + "message": "be filtravimo", "description": "Name of blocking mode 0" }, "filteringMode1Name": { - "message": "basic", + "message": "pagrindinis", "description": "Name of blocking mode 1" }, "filteringMode2Name": { - "message": "optimal", + "message": "optimalus", "description": "Name of blocking mode 2" }, "filteringMode3Name": { - "message": "complete", + "message": "pilnas", "description": "Name of blocking mode 3" }, "basicFilteringModeDescription": { - "message": "Basic network filtering from selected filter lists.\n\nDoes not require permission to read and modify data on websites.", + "message": "Pagrindinis tinklo filtravimas pagal pasirinktus filtrų sąrašus.\n\nNereikalauja leidimo skaityti ir keisti duomenis svetainėse.", "description": "This describes the 'basic' filtering mode" }, "optimalFilteringModeDescription": { - "message": "Advanced network filtering plus specific extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.", + "message": "Išplėstinis tinklo filtravimas ir specifinis išplėstinis filtravimas pagal pasirinktus filtrų sąrašus.\n\nReikalauja plataus leidimo skaityti ir keisti duomenis visose svetainėse.", "description": "This describes the 'optimal' filtering mode" }, "completeFilteringModeDescription": { - "message": "Advanced network filtering plus specific and generic extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.\n\nGeneric extended filtering may cause higher web page resources usage.", + "message": "Išplėstinis tinklo filtravimas ir specifinis bei bendrasis išplėstinis filtravimas pagal pasirinktus filtrų sąrašus.\n\nReikalauja plataus leidimo skaityti ir keisti duomenis visose svetainėse.\n\nBendrasis išplėstinis filtravimas gali padidinti tinklalapio išteklių naudojimą.", "description": "This describes the 'complete' filtering mode" }, "noFilteringModeDescription": { - "message": "List of websites for which no filtering will take place.", + "message": "Svetainių, kuriose filtravimas nebus atliekamas, sąrašas.", "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { - "message": "[hostnames only]\nexample.com\ngames.example\n...", + "message": "[tik kompiuterių vardai]\nexample.com\ngames.example\n...", "description": "Default text for in edit field" }, "behaviorSectionLabel": { @@ -244,179 +268,195 @@ "description": "Label for a checkbox in the options page" }, "showBlockedCountLabel": { - "message": "Show the number of blocked requests on the toolbar icon", + "message": "Rodyti užblokuotų užklausų skaičių įrankių juostos piktogramoje", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "Enable strict blocking", + "message": "Įjungti griežtą blokavimą", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "Navigacija į potencialiai nepageidaujamas svetaines bus blokuojama, ir jums bus pasiūlyta galimybė tęsti.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Įjungti iššokančiųjų langų blokavimą", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Kai aktyvu, atitinkantys filtrai automatiškai uždarys nepageidaujamas naršyklės korteles, sukurtas svetainių.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Filtrų kūrimo smėlio dėžė", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Developer mode", + "message": "Kūrėjo režimas", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "Suteikia prieigą prie funkcijų, tinkamų techniniams vartotojams.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "Atsarginė kopija", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "Sukurkite atsarginę pasirinktinių nustatymų kopiją faile arba atkurkite pasirinktinius nustatymus iš failo.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "Atkūrimas perrašys visus jūsų dabartinius pasirinktinius nustatymus.", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "Find lists", + "message": "Ieškoti sąrašų", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { - "message": "Page blocked", + "message": "Puslapis užblokuotas", "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite has prevented the following page from loading:", + "message": "uBO Lite neleido įkelti šio puslapio:", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "The page was blocked because of a matching filter in {{listname}}.", + "message": "Puslapis buvo užblokuotas dėl atitinkančio filtro sąraše {{listname}}.", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "Užblokuotas puslapis nori nukreipti į kitą svetainę. Jei nuspręsite tęsti, būsite tiesiogiai nukreipti į: {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { - "message": "without parameters", + "message": "be parametrų", "description": "Label to be used for the parameter-less URL" }, "strictblockBack": { - "message": "Go back", + "message": "Grįžti atgal", "description": "A button to go back to the previous web page" }, "strictblockClose": { - "message": "Close this window", + "message": "Uždaryti šį langą", "description": "A button to close the current tab" }, "strictblockDontWarn": { - "message": "Don't warn me again about this site", + "message": "Daugiau neįspėti manęs apie šią svetainę", "description": "Label for checkbox in document-blocked page" }, "strictblockProceed": { - "message": "Proceed", + "message": "Tęsti", "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Remove an element", + "message": "Pašalinti elementą", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Exit element zapper mode", + "message": "Išeiti iš elementų šalinimo režimo", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "Sukurti pasirinktinį filtrą", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "Pašalinti pasirinktinį filtrą", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { - "message": "View:", + "message": "Peržiūrėti:", "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "Filtravimo režimo informacija", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "Pasirinktinės DNR taisyklės", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "DNR taisyklės iš …", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "Dinaminis taisyklių rinkinys", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "Sesijos taisyklių rinkinys", "description": "An option in a dropdown list" }, "saveButton": { - "message": "Save", + "message": "Išsaugoti", "description": "Text for buttons used to save changes" }, "revertButton": { - "message": "Revert", + "message": "Atšaukti", "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "Add", + "message": "Pridėti", "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Import and append…", + "message": "Importuoti ir pridėti…", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Export…", + "message": "Eksportuoti…", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "Kurti atsarginę kopiją…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "Atkurti…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "Atkurti numatytuosius nustatymus…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "Visi jūsų pasirinktiniai nustatymai bus pašalinti. Ar tikrai norite atkurti numatytuosius nustatymus?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "Nepridėkite turinio iš nepatikimų šaltinių", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "Registruotų taisyklių skaičius: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "Perkelkite slankiklį, kad pasirinktumėte geriausią atitikmenį", "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Pick", + "message": "Pasirinkti", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "Peržiūra", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "Sukurti", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "Pasirinkite filtrą žemiau, kad paryškintumėte atitinkančius elementus tinklalapyje. Spustelėkite šiukšliadėžę, kad pašalintumėte filtrą.", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/lv/messages.json b/platform/mv3/extension/_locales/lv/messages.json index 6d858f1dc500e..66b96d7d27f35 100644 --- a/platform/mv3/extension/_locales/lv/messages.json +++ b/platform/mv3/extension/_locales/lv/messages.json @@ -35,6 +35,10 @@ "message": "Konfidencialitātes nosacījumi", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Dokumentācija", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "aizturēšanas veids", "description": "Label in the popup panel for the current filtering mode" @@ -87,6 +91,22 @@ "message": "Apgabali, valodas", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Imported lists", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Add filter list…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL of the filter list to add", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Ievietot/izgūt", "description": "Text label heading the import/export area of custom filters" @@ -95,6 +115,10 @@ "message": "Šeit ir ielīmējami noteikti kosmētiskie aizturētāji, kurus pievienot", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Open your browser's extensions page (chrome://extensions in Chrome or about:addons in Firefox), open uBO Lite details, and toggle on Allow user scripts (also referred to as “unverified third-party scripts”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Izmaiņu žurnāls", "description": "" @@ -255,6 +279,22 @@ "message": "Iespējami nevēlamu vietņu apmeklēšana tiks aizturēta, un tiks piedāvāta iespēja turpināt.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Iesspējot uzlecošos logu aizturēšanu", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Kad ieslēgts, atbilstošie aizturētāji automātiski aizvērs tīmekļvietņu izveidotas nevēlamas pārlūka cilnes.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Aizturētāju izveidošanas smilškaste", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Izstrādātāja režīms", "description": "Label for a checkbox in the options page" @@ -316,7 +356,7 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Pārslēgties uz elementu iznīcināšanu", + "message": "Noņemt elementu", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { diff --git a/platform/mv3/extension/_locales/mk/messages.json b/platform/mv3/extension/_locales/mk/messages.json index f80ea18cb57f3..cf727102e5628 100644 --- a/platform/mv3/extension/_locales/mk/messages.json +++ b/platform/mv3/extension/_locales/mk/messages.json @@ -35,6 +35,10 @@ "message": "Полиса за личните податоци", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Документација", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "модови на филтрирање", "description": "Label in the popup panel for the current filtering mode" @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Malware protection, security", + "message": "Заштита од малициозен софтвер, безбедност", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,14 +91,34 @@ "message": "Региони, јазици", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Увезени листи", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Додај листа на филтри…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL на листата на филтри за додавање", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Увоз / Извоз", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "Специфични козметички/скриплет филтри за додавање", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Отворете ја страницата за проширувања на вашиот прелистувач (chrome://extensions во Chrome или about:addons во Firefox), отворете ги деталите за uBO Lite и вклучете ја опцијата Дозволи кориснички скрипти (исто така наречени „непроверени скрипти од трети страни“).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Промени", "description": "" @@ -252,15 +276,31 @@ "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "Навигацијата кон потенцијално непожелни страници ќе биде блокирана и ќе ви биде понудена опција да продолжите.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Овозможи блокирање на искачувачки прозорци", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Кога е активно, соодветните филтри автоматски ќе ги затвораат непожелните јазичиња во прелистувачот создадени од веб-страниците.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Песочник за креирање филтри", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Мод за девелопери", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "Овозможува пристап до функции погодни за технички корисници.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { @@ -268,11 +308,11 @@ "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "Направете резервна копија на вашите сопствени поставки во датотека или вратете ги вашите сопствени поставки од датотека.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "Враќањето ќе ги пребрише сите ваши тековни сопствени поставки.", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { @@ -284,15 +324,15 @@ "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite has prevented the following page from loading:", + "message": "uBO Lite го спречи вчитувањето на следната страница:", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "The page was blocked because of a matching filter in {{listname}}.", + "message": "Страницата беше блокирана поради соодветен филтер во {{listname}}.", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "Блокираната страница сака да пренасочи кон друга страница. Ако изберете да продолжите, ќе бидете пренасочени директно на: {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { @@ -320,15 +360,15 @@ "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Exit element zapper mode", + "message": "Излези од режимот за отстранување елементи", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "Креирај сопствен филтер", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "Отстрани сопствен филтер", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { @@ -336,15 +376,15 @@ "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "Детали за режимот на филтрирање", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "Сопствени DNR правила", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "DNR правила на …", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { @@ -380,27 +420,27 @@ "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "Врати…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "Ресетирај на стандардните поставки…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "Сите ваши сопствени поставки ќе бидат отстранети. Дали навистина сакате да ги ресетирате на стандардните поставки?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "Не додавајте содржина од недоверливи извори", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "Број на регистрирани правила: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "Поместете го лизгачот за да го изберете најдоброто совпаѓање", "description": "Label to describe the purpose of the slider" }, "pickerPick": { @@ -408,15 +448,15 @@ "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "Преглед", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "Креирај", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "Изберете филтер подолу за да ги означите соодветните елементи на веб-страницата. Кликнете на кантата за отстранување на филтер.", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/ml/messages.json b/platform/mv3/extension/_locales/ml/messages.json index e4211af439dc5..3cc50e122a232 100644 --- a/platform/mv3/extension/_locales/ml/messages.json +++ b/platform/mv3/extension/_locales/ml/messages.json @@ -20,11 +20,11 @@ "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "Custom filters", + "message": "ഇഷ്ടാനുസൃത ഫിൽറ്ററുകൾ", "description": "appears as tab name in dashboard" }, "developPageName": { - "message": "Develop", + "message": "വികസനം", "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { @@ -35,16 +35,20 @@ "message": "സ്വകാര്യതാ നയം", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "ഡോക്യുമെന്റേഷൻ", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "ഫിൽട്ടറിംഗ് മോഡ്", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "On this website", + "message": "ഈ വെബ്സൈറ്റിൽ", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "Report an issue", + "message": "ഒരു പ്രശ്നം റിപ്പോർട്ട് ചെയ്യുക", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Malware protection, security", + "message": "മാൽവെയർ സംരക്ഷണം, സുരക്ഷ", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,14 +91,34 @@ "message": "പ്രാദേശികം, ഭാഷകള്‍", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "ഇറക്കുമതി ചെയ്ത ലിസ്റ്റുകൾ", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "ഫിൽറ്റർ ലിസ്റ്റ് ചേർക്കുക…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "ചേർക്കേണ്ട ഫിൽറ്റർ ലിസ്റ്റിന്റെ URL", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { - "message": "Import / Export", + "message": "ഇറക്കുമതി / കയറ്റുമതി", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "ചേർക്കേണ്ട പ്രത്യേക കോസ്മെറ്റിക്/സ്ക്രിപ്റ്റ്ലെറ്റ് ഫിൽറ്ററുകൾ", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "നിങ്ങളുടെ ബ്രൗസറിന്റെ എക്സ്റ്റൻഷനുകൾ പേജ് തുറക്കുക (Chrome-ൽ chrome://extensions അല്ലെങ്കിൽ Firefox-ൽ about:addons), uBO Lite വിശദാംശങ്ങൾ തുറക്കുക, യൂസർ സ്ക്രിപ്റ്റുകൾ അനുവദിക്കുക (മറ്റൊരു വിധത്തിൽ “പരിശോധിക്കാത്ത മൂന്നാം കക്ഷി സ്ക്രിപ്റ്റുകൾ” എന്നും അറിയപ്പെടുന്നു) ടോഗിൾ ഓണാക്കുക.", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "ചേഞ്ച് ലോഗ്", "description": "" @@ -124,71 +148,71 @@ "description": "Shown in the About pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "ഒരു ഫിൽട്ടർ പ്രശ്നം റിപ്പോർട്ട് ചെയ്യുക", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "പ്രത്യേക വെബ്സൈറ്റുകളിലെ ഫിൽറ്റർ പ്രശ്നങ്ങൾ uBlockOrigin/uAssets ഇഷ്യു ട്രാക്കറിൽ റിപ്പോർട്ട് ചെയ്യുക. ഒരു GitHub അക്കൗണ്ട് ആവശ്യമാണ്.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting information", + "message": "പ്രശ്നപരിഹാര വിവരങ്ങൾ", "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "ആവർത്തിച്ചുള്ള റിപ്പോർട്ടുകൾ ഉപയോഗിച്ച് സന്നദ്ധപ്രവർത്തകരെ ബുദ്ധിമുട്ടിക്കുന്നത് ഒഴിവാക്കാൻ, പ്രശ്നം നേരത്തെ റിപ്പോർട്ട് ചെയ്തിട്ടില്ലെന്ന് ദയവായി ഉറപ്പാക്കുക. ശ്രദ്ധിക്കുക: ബട്ടൺ ക്ലിക്ക് ചെയ്യുന്നത് പേജിന്റെ ഉത്ഭവം GitHub-ലേക്ക് അയയ്ക്കുന്നതിന് കാരണമാകും.", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "GitHub-ൽ സമാനമായ റിപ്പോർട്ടുകൾ കണ്ടെത്തുക", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "വെബ് പേജിന്റെ വിലാസം:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "വെബ് പേജ്…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- ഒരു എൻട്രി തിരഞ്ഞെടുക്കുക --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "പരസ്യങ്ങളോ പരസ്യ അവശിഷ്ടങ്ങളോ കാണിക്കുന്നു", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "ഓവർലേകളോ മറ്റ് ശല്യങ്ങളോ ഉണ്ട്", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBO Lite", + "message": "uBO Lite-നെ കണ്ടെത്തുന്നു", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "സ്വകാര്യത-സംബന്ധമായ പ്രശ്നങ്ങൾ ഉണ്ട്", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBO Lite is enabled", + "message": "uBO Lite പ്രവർത്തനക്ഷമമാകുമ്പോൾ തകരാറിലാകുന്നു", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "അനാവശ്യ ടാബുകളോ വിൻഡോകളോ തുറക്കുന്നു", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "ബാഡ്വെയർ, ഫിഷിംഗ് എന്നിവയിലേക്ക് നയിക്കുന്നു", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "വെബ് പേജിനെ “NSFW” എന്ന് ലേബൽ ചെയ്യുക (“ജോലിക്ക് സുരക്ഷിതമല്ല”)", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "GitHub-ൽ പുതിയ റിപ്പോർട്ട് സൃഷ്ടിക്കുക", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { @@ -232,7 +256,7 @@ "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { - "message": "[hostnames only]\nexample.com\ngames.example\n...", + "message": "[ഹോസ്റ്റ്നെയിമുകൾ മാത്രം]\nexample.com\ngames.example\n...", "description": "Default text for in edit field" }, "behaviorSectionLabel": { @@ -244,179 +268,195 @@ "description": "Label for a checkbox in the options page" }, "showBlockedCountLabel": { - "message": "Show the number of blocked requests on the toolbar icon", + "message": "ടൂൾബാർ ഐക്കണിൽ തടഞ്ഞ അഭ്യർത്ഥനകളുടെ എണ്ണം കാണിക്കുക", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "Enable strict blocking", + "message": "കർശനമായ തടയൽ പ്രവർത്തനക്ഷമമാക്കുക", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "സാധ്യതയുള്ള അനഭിലഷണീയ സൈറ്റുകളിലേക്കുള്ള നാവിഗേഷൻ തടയപ്പെടും, കൂടാതെ മുന്നോട്ട് പോകാനുള്ള ഓപ്ഷൻ നിങ്ങൾക്ക് വാഗ്ദാനം ചെയ്യും.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "പോപ്പ്-അപ്പ് തടയൽ പ്രവർത്തനക്ഷമമാക്കുക", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "സജീവമാകുമ്പോൾ, പൊരുത്തപ്പെടുന്ന ഫിൽറ്ററുകൾ വെബ്സൈറ്റുകൾ സൃഷ്ടിക്കുന്ന അനാവശ്യ ബ്രൗസർ ടാബുകൾ യാന്ത്രികമായി അടയ്ക്കും.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "ഫിൽറ്റർ-നിർമ്മാണ സാൻഡ്ബോക്സ്", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Developer mode", + "message": "ഡെവലപ്പർ മോഡ്", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "സാങ്കേതിക ഉപയോക്താക്കൾക്ക് അനുയോജ്യമായ സവിശേഷതകളിലേക്കുള്ള ആക്സസ് പ്രാപ്തമാക്കുന്നു.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "ബാക്കപ്പ്", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "നിങ്ങളുടെ ഇഷ്ടാനുസൃത ക്രമീകരണങ്ങൾ ഒരു ഫയലിലേക്ക് ബാക്കപ്പ് ചെയ്യുക, അല്ലെങ്കിൽ ഒരു ഫയലിൽ നിന്ന് നിങ്ങളുടെ ഇഷ്ടാനുസൃത ക്രമീകരണങ്ങൾ പുനഃസ്ഥാപിക്കുക.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "പുനഃസ്ഥാപിക്കുന്നത് നിങ്ങളുടെ എല്ലാ നിലവിലെ ഇഷ്ടാനുസൃത ക്രമീകരണങ്ങളും മറികടക്കും.", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "Find lists", + "message": "ലിസ്റ്റുകൾ കണ്ടെത്തുക", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { - "message": "Page blocked", + "message": "പേജ് തടഞ്ഞു", "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite has prevented the following page from loading:", + "message": "ഇനിപ്പറയുന്ന പേജ് ലോഡാകുന്നതിൽ നിന്ന് uBO Lite തടഞ്ഞു:", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "The page was blocked because of a matching filter in {{listname}}.", + "message": "{{listname}} എന്നതിലെ പൊരുത്തപ്പെടുന്ന ഒരു ഫിൽറ്റർ കാരണം പേജ് തടഞ്ഞു.", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "തടഞ്ഞ പേജ് മറ്റൊരു സൈറ്റിലേക്ക് റീഡയറക്ട് ചെയ്യാൻ ആഗ്രഹിക്കുന്നു. നിങ്ങൾ മുന്നോട്ട് പോകാൻ തിരഞ്ഞെടുക്കുകയാണെങ്കിൽ, നിങ്ങൾ നേരിട്ട് ഇങ്ങോട്ട് നാവിഗേറ്റ് ചെയ്യും: {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { - "message": "without parameters", + "message": "പാരാമീറ്ററുകൾ ഇല്ലാതെ", "description": "Label to be used for the parameter-less URL" }, "strictblockBack": { - "message": "Go back", + "message": "തിരികെ പോകുക", "description": "A button to go back to the previous web page" }, "strictblockClose": { - "message": "Close this window", + "message": "ഈ വിൻഡോ അടയ്ക്കുക", "description": "A button to close the current tab" }, "strictblockDontWarn": { - "message": "Don't warn me again about this site", + "message": "ഈ സൈറ്റിനെക്കുറിച്ച് വീണ്ടും എന്നെ മുന്നറിയിപ്പ് നൽകരുത്", "description": "Label for checkbox in document-blocked page" }, "strictblockProceed": { - "message": "Proceed", + "message": "മുന്നോട്ട് പോകുക", "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Remove an element", + "message": "ഒരു മൂലകം നീക്കം ചെയ്യുക", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Exit element zapper mode", + "message": "എലമെന്റ് സാപ്പർ മോഡിൽ നിന്ന് പുറത്തുകടക്കുക", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "ഒരു ഇഷ്ടാനുസൃത ഫിൽട്ടർ സൃഷ്ടിക്കുക", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "ഒരു ഇഷ്ടാനുസൃത ഫിൽട്ടർ നീക്കം ചെയ്യുക", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { - "message": "View:", + "message": "കാണുക:", "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "ഫിൽട്ടറിംഗ് മോഡ് വിശദാംശങ്ങൾ", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "ഇഷ്ടാനുസൃത DNR നിയമങ്ങൾ", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "… ന്റെ DNR നിയമങ്ങൾ", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "ഡൈനാമിക് റൂൾസെറ്റ്", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "സെഷൻ റൂൾസെറ്റ്", "description": "An option in a dropdown list" }, "saveButton": { - "message": "Save", + "message": "സംരക്ഷിക്കുക", "description": "Text for buttons used to save changes" }, "revertButton": { - "message": "Revert", + "message": "പഴയപടിയാക്കുക", "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "Add", + "message": "ചേർക്കുക", "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Import and append…", + "message": "ഇറക്കുമതി ചെയ്ത് കൂട്ടിച്ചേർക്കുക…", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Export…", + "message": "കയറ്റുമതി…", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "ബാക്കപ്പ്…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "പുനഃസ്ഥാപിക്കുക…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "സ്ഥിരസ്ഥിതി ക്രമീകരണങ്ങളിലേക്ക് പുനഃസജ്ജമാക്കുക…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "നിങ്ങളുടെ എല്ലാ ഇഷ്ടാനുസൃത ക്രമീകരണങ്ങളും നീക്കം ചെയ്യപ്പെടും. സ്ഥിരസ്ഥിതി ക്രമീകരണങ്ങളിലേക്ക് പുനഃസജ്ജമാക്കാൻ നിങ്ങൾക്ക് ശരിക്കും ആഗ്രഹമുണ്ടോ?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "വിശ്വസനീയമല്ലാത്ത ഉറവിടങ്ങളിൽ നിന്ന് ഉള്ളടക്കം ചേർക്കരുത്", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "രജിസ്റ്റർ ചെയ്ത നിയമങ്ങളുടെ എണ്ണം: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "ഏറ്റവും മികച്ച പൊരുത്തം തിരഞ്ഞെടുക്കാൻ സ്ലൈഡർ നീക്കുക", "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Pick", + "message": "തിരഞ്ഞെടുക്കുക", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "പ്രിവ്യൂ", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "സൃഷ്ടിക്കുക", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "വെബ് പേജിലെ പൊരുത്തപ്പെടുന്ന മൂലകങ്ങൾ ഹൈലൈറ്റ് ചെയ്യാൻ ചുവടെയുള്ള ഒരു ഫിൽട്ടർ തിരഞ്ഞെടുക്കുക. ഒരു ഫിൽട്ടർ നീക്കം ചെയ്യാൻ ട്രാഷ് ഐക്കൺ ക്ലിക്ക് ചെയ്യുക.", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/mr/messages.json b/platform/mv3/extension/_locales/mr/messages.json index 881b780e38fa2..410b3f8b85fb1 100644 --- a/platform/mv3/extension/_locales/mr/messages.json +++ b/platform/mv3/extension/_locales/mr/messages.json @@ -4,419 +4,459 @@ "description": "extension name." }, "extShortDesc": { - "message": "An efficient content blocker. Blocks ads, trackers, miners, and more immediately upon installation.", + "message": "एक कार्यक्षम सामग्री ब्लॉकर. स्थापनेनंतर लगेच जाहिराती, ट्रॅकर्स, मायनर्स आणि बरेच काही अवरोधित करते.", "description": "this will be in the Chrome web store: must be 132 characters or less" }, "perRulesetStats": { - "message": "{{ruleCount}} rules, converted from {{filterCount}} network filters", + "message": "{{filterCount}} नेटवर्क फिल्टरमधून रूपांतरित {{ruleCount}} नियम", "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "dashboardName": { - "message": "uBO Lite — Dashboard", + "message": "uBO Lite — डॅशबोर्ड", "description": "English: uBO Lite — Dashboard" }, "settingsPageName": { - "message": "Settings", + "message": "सेटिंग्ज", "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "Custom filters", + "message": "सानुकूल फिल्टर", "description": "appears as tab name in dashboard" }, "developPageName": { - "message": "Develop", + "message": "विकसित करा", "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { - "message": "About", + "message": "विषयी", "description": "appears as tab name in dashboard" }, "aboutPrivacyPolicy": { - "message": "Privacy policy", + "message": "गोपनीयता धोरण", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "दस्तऐवजीकरण", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { - "message": "filtering mode", + "message": "फिल्टरिंग मोड", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "On this website", + "message": "या वेबसाइटवर", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "Report an issue", + "message": "समस्या कळवा", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { - "message": "Open the dashboard", + "message": "डॅशबोर्ड उघडा", "description": "English: Click to open the dashboard" }, "popupMoreButton": { - "message": "More", + "message": "अधिक", "description": "Label to be used to show popup panel sections" }, "popupLessButton": { - "message": "Less", + "message": "कमी", "description": "Label to be used to hide popup panel sections" }, "3pGroupDefault": { - "message": "Default", + "message": "डीफॉल्ट", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAds": { - "message": "Ads", + "message": "जाहिराती", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupPrivacy": { - "message": "Privacy", + "message": "गोपनीयता", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Malware protection, security", + "message": "मालवेअरपासून संरक्षण, सुरक्षा", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { - "message": "Annoyances", + "message": "त्रासदायक घटक", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMisc": { - "message": "Miscellaneous", + "message": "विविध", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupRegions": { - "message": "Regions, languages", + "message": "प्रदेश, भाषा", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "3pGroupImported": { + "message": "आयात केलेल्या याद्या", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "customListImportLabel": { + "message": "फिल्टर यादी जोडा…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "जोडायच्या फिल्टर यादीचा URL", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { - "message": "Import / Export", + "message": "आयात / निर्यात", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "जोडायचे विशिष्ट कॉस्मेटिक/स्क्रिप्टलेट फिल्टर", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "तुमच्या ब्राउझरचे विस्तारण पृष्ठ उघडा (Chrome मध्ये chrome://extensions किंवा Firefox मध्ये about:addons), uBO Lite तपशील उघडा, आणि Allow user scripts (ज्याला “unverified third-party scripts” असेही म्हणतात) टॉगल चालू करा.", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { - "message": "Changelog", + "message": "बदल नोंदवही", "description": "" }, "aboutCode": { - "message": "Source code (GPLv3)", + "message": "सोर्स कोड (GPLv3)", "description": "English: Source code (GPLv3)" }, "aboutContributors": { - "message": "Contributors", + "message": "योगदानकर्ते", "description": "English: Contributors" }, "aboutSourceCode": { - "message": "Source code", + "message": "सोर्स कोड", "description": "Link text to source code repo" }, "aboutTranslations": { - "message": "Translations", + "message": "अनुवाद", "description": "Link text to translations repo" }, "aboutFilterLists": { - "message": "Filter lists", + "message": "फिल्टर याद्या", "description": "Link text to uBO's own filter lists repo" }, "aboutDependencies": { - "message": "External dependencies (GPLv3-compatible):", + "message": "बाह्य अवलंबित्वे (GPLv3-सुसंगत):", "description": "Shown in the About pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "फिल्टर समस्या कळवा", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "विशिष्ट वेबसाइट्सवरील फिल्टर समस्या uBlockOrigin/uAssets समस्या ट्रॅकरला कळवा. GitHub खाते आवश्यक आहे.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting information", + "message": "समस्या निवारण माहिती", "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "स्वयंसेवकांवर डुप्लिकेट अहवालांचा भार टाळण्यासाठी, कृपया ही समस्या आधीपासून अहवाल केली गेली नाही याची पडताळणी करा. सूचना: बटण क्लिक केल्याने पृष्ठाचे मूळ (origin) GitHub वर पाठवले जाईल.", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "GitHub वर समान अहवाल शोधा", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "वेब पृष्ठाचा पत्ता:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "वेब पृष्ठ…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- एक नोंद निवडा --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "जाहिराती किंवा जाहिरातीचे अवशेष दाखवते", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "ओव्हरले किंवा इतर त्रासदायक घटक आहेत", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBO Lite", + "message": "uBO Lite शोधते", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "गोपनीयता-संबंधित समस्या आहेत", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBO Lite is enabled", + "message": "uBO Lite सक्षम असताना कार्यात अडथळा येतो", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "अवांछित टॅब किंवा विंडो उघडते", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "बॅडवेअर, फिशिंगकडे नेतो", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "वेब पृष्ठाला “NSFW” (“Not Safe For Work”) म्हणून लेबल करा", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "GitHub वर नवीन अहवाल तयार करा", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { - "message": "Default filtering mode", + "message": "डीफॉल्ट फिल्टरिंग मोड", "description": "The header text for the default filtering mode section" }, "defaultFilteringModeDescription": { - "message": "The default filtering mode will be overridden by per-website filtering modes. You can adjust the filtering mode on any given website according to whichever mode works best on that website. Each mode has its advantages and disadvantages.", + "message": "डीफॉल्ट फिल्टरिंग मोड प्रति-वेबसाइट फिल्टरिंग मोडद्वारे बदलला जाईल. कोणत्याही वेबसाइटवर कोणता मोड सर्वोत्तम कार्य करतो त्यानुसार तुम्ही फिल्टरिंग मोड समायोजित करू शकता. प्रत्येक मोडचे स्वतःचे फायदे आणि तोटे आहेत.", "description": "This describes the default filtering mode setting" }, "filteringMode0Name": { - "message": "no filtering", + "message": "फिल्टरिंग नाही", "description": "Name of blocking mode 0" }, "filteringMode1Name": { - "message": "basic", + "message": "मूलभूत", "description": "Name of blocking mode 1" }, "filteringMode2Name": { - "message": "optimal", + "message": "इष्टतम", "description": "Name of blocking mode 2" }, "filteringMode3Name": { - "message": "complete", + "message": "पूर्ण", "description": "Name of blocking mode 3" }, "basicFilteringModeDescription": { - "message": "Basic network filtering from selected filter lists.\n\nDoes not require permission to read and modify data on websites.", + "message": "निवडलेल्या फिल्टर याद्यांमधून मूलभूत नेटवर्क फिल्टरिंग.\n\nवेबसाइट्सवरील डेटा वाचण्यासाठी आणि सुधारण्यासाठी परवानगी आवश्यक नाही.", "description": "This describes the 'basic' filtering mode" }, "optimalFilteringModeDescription": { - "message": "Advanced network filtering plus specific extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.", + "message": "निवडलेल्या फिल्टर याद्यांमधून प्रगत नेटवर्क फिल्टरिंग आणि विशिष्ट विस्तारित फिल्टरिंग.\n\nसर्व वेबसाइट्सवरील डेटा वाचण्यासाठी आणि सुधारण्यासाठी व्यापक परवानगी आवश्यक आहे.", "description": "This describes the 'optimal' filtering mode" }, "completeFilteringModeDescription": { - "message": "Advanced network filtering plus specific and generic extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.\n\nGeneric extended filtering may cause higher web page resources usage.", + "message": "निवडलेल्या फिल्टर याद्यांमधून प्रगत नेटवर्क फिल्टरिंग आणि विशिष्ट आणि सामान्य विस्तारित फिल्टरिंग.\n\nसर्व वेबसाइट्सवरील डेटा वाचण्यासाठी आणि सुधारण्यासाठी व्यापक परवानगी आवश्यक आहे.\n\nसामान्य विस्तारित फिल्टरिंगमुळे वेब पृष्ठ संसाधनांचा वापर वाढू शकतो.", "description": "This describes the 'complete' filtering mode" }, "noFilteringModeDescription": { - "message": "List of websites for which no filtering will take place.", + "message": "ज्या वेबसाइट्ससाठी कोणतेही फिल्टरिंग होणार नाही अशी यादी.", "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { - "message": "[hostnames only]\nexample.com\ngames.example\n...", + "message": "[फक्त होस्टनेम]\nexample.com\ngames.example\n...", "description": "Default text for in edit field" }, "behaviorSectionLabel": { - "message": "Behavior", + "message": "वर्तन", "description": "The header text for the 'Behavior' section" }, "autoReloadLabel": { - "message": "Automatically reload page when changing filtering mode", + "message": "फिल्टरिंग मोड बदलताना पृष्ठ स्वयंचलितपणे पुन्हा लोड करा", "description": "Label for a checkbox in the options page" }, "showBlockedCountLabel": { - "message": "Show the number of blocked requests on the toolbar icon", + "message": "टूलबार चिन्हावर अवरोधित केलेल्या विनंत्यांची संख्या दाखवा", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "Enable strict blocking", + "message": "कठोर अवरोधन सक्षम करा", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "संभाव्य अवांछित साइट्सवरील नेव्हिगेशन अवरोधित केले जाईल, आणि तुम्हाला पुढे जाण्याचा पर्याय दिला जाईल.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "पॉप-अप अवरोधन सक्षम करा", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "सक्रिय असताना, जुळणारे फिल्टर वेबसाइट्सद्वारे तयार केलेले अवांछित ब्राउझर टॅब स्वयंचलितपणे बंद करतील.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "फिल्टर-निर्मिती सँडबॉक्स", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Developer mode", + "message": "विकासक मोड", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "तांत्रिक वापरकर्त्यांसाठी योग्य वैशिष्ट्यांमध्ये प्रवेश सक्षम करते.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "बॅकअप", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "तुमच्या सानुकूल सेटिंग्ज फाइलमध्ये बॅकअप करा, किंवा फाइलमधून तुमच्या सानुकूल सेटिंग्ज पुनर्संचयित करा.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "पुनर्संचयित केल्याने तुमच्या सर्व सध्याच्या सानुकूल सेटिंग्ज अधिलिखित होतील.", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "Find lists", + "message": "याद्या शोधा", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { - "message": "Page blocked", + "message": "पृष्ठ अवरोधित", "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite has prevented the following page from loading:", + "message": "uBO Lite ने खालील पृष्ठ लोड होण्यापासून रोखले आहे:", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "The page was blocked because of a matching filter in {{listname}}.", + "message": "{{listname}} मधील जुळणाऱ्या फिल्टरमुळे पृष्ठ अवरोधित केले गेले.", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "अवरोधित पृष्ठ दुसऱ्या साइटवर पुनर्निर्देशित करू इच्छित आहे. तुम्ही पुढे जाण्याचे निवडल्यास, तुम्ही थेट येथे नेव्हिगेट कराल: {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { - "message": "without parameters", + "message": "पॅरामीटर्सशिवाय", "description": "Label to be used for the parameter-less URL" }, "strictblockBack": { - "message": "Go back", + "message": "मागे जा", "description": "A button to go back to the previous web page" }, "strictblockClose": { - "message": "Close this window", + "message": "ही विंडो बंद करा", "description": "A button to close the current tab" }, "strictblockDontWarn": { - "message": "Don't warn me again about this site", + "message": "या साइटबद्दल मला पुन्हा इशारा देऊ नका", "description": "Label for checkbox in document-blocked page" }, "strictblockProceed": { - "message": "Proceed", + "message": "पुढे जा", "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Remove an element", + "message": "एलिमेंट काढा", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Exit element zapper mode", + "message": "एलिमेंट झापर मोडमधून बाहेर पडा", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "सानुकूल फिल्टर तयार करा", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "सानुकूल फिल्टर काढा", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { - "message": "View:", + "message": "पहा:", "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "फिल्टरिंग मोड तपशील", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "सानुकूल DNR नियम", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "... चे DNR नियम", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "डायनॅमिक नियमसंच", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "सत्र नियमसंच", "description": "An option in a dropdown list" }, "saveButton": { - "message": "Save", + "message": "जतन करा", "description": "Text for buttons used to save changes" }, "revertButton": { - "message": "Revert", + "message": "पूर्ववत करा", "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "Add", + "message": "जोडा", "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Import and append…", + "message": "आयात करा आणि जोडा…", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Export…", + "message": "निर्यात करा…", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "बॅकअप करा…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "पुनर्संचयित करा…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "डीफॉल्ट सेटिंग्जमध्ये रीसेट करा…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "तुमच्या सर्व सानुकूल सेटिंग्ज काढून टाकल्या जातील. तुम्हाला खरोखर डीफॉल्ट सेटिंग्जमध्ये रीसेट करायचे आहे का?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "अविश्वसनीय स्रोतांकडून सामग्री जोडू नका", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "नोंदणीकृत नियमांची संख्या: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "सर्वोत्तम जुळणी निवडण्यासाठी स्लायडर हलवा", "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Pick", + "message": "निवडा", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "पूर्वावलोकन", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "तयार करा", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "वेब पृष्ठावर जुळणारे एलिमेंट हायलाइट करण्यासाठी खालील फिल्टर निवडा. फिल्टर काढण्यासाठी कचरापेटीवर क्लिक करा.", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/ms/messages.json b/platform/mv3/extension/_locales/ms/messages.json index d88bf60beac79..663a1a4e7702d 100644 --- a/platform/mv3/extension/_locales/ms/messages.json +++ b/platform/mv3/extension/_locales/ms/messages.json @@ -20,11 +20,11 @@ "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "Custom filters", + "message": "Penapis tersuai", "description": "appears as tab name in dashboard" }, "developPageName": { - "message": "Develop", + "message": "Pembangunan", "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { @@ -35,16 +35,20 @@ "message": "Dasar privasi", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Dokumentasi", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "mod penapisan", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "On this website", + "message": "Pada laman web ini", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "Report an issue", + "message": "Laporkan masalah", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Malware protection, security", + "message": "Perlindungan perisian hasad, keselamatan", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,14 +91,34 @@ "message": "Wilayah, bahasa", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Senarai diimport", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Tambah senarai penapis…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL senarai penapis untuk ditambah", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { - "message": "Import / Export", + "message": "Import / Eksport", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "Penapis kosmetik/scriptlet khusus untuk ditambah", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Buka halaman sambungan pelayar anda (chrome://extensions dalam Chrome atau about:addons dalam Firefox), buka butiran uBO Lite, dan aktifkan Benarkan skrip pengguna (juga dirujuk sebagai \"skrip pihak ketiga yang tidak disahkan\").", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Log perubahan", "description": "" @@ -124,71 +148,71 @@ "description": "Shown in the About pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "Laporkan isu penapis", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "Laporkan isu penapis dengan laman web tertentu kepada uBlockOrigin/uAssets penjejak isu. Memerlukan akaun GitHub.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting information", + "message": "Maklumat penyelesaian masalah", "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "Untuk mengelakkan membebankan sukarelawan dengan laporan yang berulang, sila pastikan isu tersebut belum dilaporkan. Nota: mengklik butang akan menyebabkan asal-usul halaman dihantar ke GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "Cari laporan serupa di GitHub", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "Alamat laman web:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "Laman web…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- Pilih satu entri --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "Menunjukkan iklan atau sisa iklan", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "Mempunyai tindanan atau gangguan lain", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBO Lite", + "message": "Mengesan uBO Lite", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "Mempunyai isu berkaitan privasi", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBO Lite is enabled", + "message": "Berfungsi dengan tidak betul apabila uBO Lite diaktifkan", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "Membuka tab atau tetingkap yang tidak diingini", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "Membawa kepada perisian hasad, pancingan data", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "Labelkan laman web sebagai “NSFW” (“Tidak Selamat Untuk Kerja”)", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "Buat laporan baharu di GitHub", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { @@ -232,7 +256,7 @@ "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { - "message": "[hostnames only]\nexample.com\ngames.example\n...", + "message": "[nama hos sahaja]\nexample.com\ngames.example\n...", "description": "Default text for in edit field" }, "behaviorSectionLabel": { @@ -248,175 +272,191 @@ "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "Enable strict blocking", + "message": "Aktifkan sekatan ketat", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "Navigasi ke laman yang berpotensi tidak diingini akan disekat, dan anda akan ditawarkan pilihan untuk meneruskan.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Aktifkan penyekatan pop timbul", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Apabila aktif, penapis yang sepadan akan menutup secara automatik tab pelayar yang tidak diingini yang dicipta oleh laman web.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Kotak pasir penciptaan penapis", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Developer mode", + "message": "Mod pembangun", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "Membolehkan akses kepada ciri yang sesuai untuk pengguna teknikal.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "Sandaran", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "Sandarkan tetapan tersuai anda ke fail, atau pulihkan tetapan tersuai anda daripada fail.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "Pemulihan akan menimpa semua tetapan tersuai semasa anda.", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "Find lists", + "message": "Cari senarai", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { - "message": "Page blocked", + "message": "Halaman disekat", "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite has prevented the following page from loading:", + "message": "uBO Lite telah menghalang halaman berikut daripada dimuatkan:", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "The page was blocked because of a matching filter in {{listname}}.", + "message": "Halaman ini disekat kerana penapis yang sepadan dalam {{listname}}.", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "Halaman yang disekat ingin melencong ke laman lain. Jika anda memilih untuk meneruskan, anda akan melayari terus ke: {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { - "message": "without parameters", + "message": "tanpa parameter", "description": "Label to be used for the parameter-less URL" }, "strictblockBack": { - "message": "Go back", + "message": "Kembali", "description": "A button to go back to the previous web page" }, "strictblockClose": { - "message": "Close this window", + "message": "Tutup tetingkap ini", "description": "A button to close the current tab" }, "strictblockDontWarn": { - "message": "Don't warn me again about this site", + "message": "Jangan amarkan saya lagi tentang laman ini", "description": "Label for checkbox in document-blocked page" }, "strictblockProceed": { - "message": "Proceed", + "message": "Teruskan", "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Remove an element", + "message": "Alih keluar elemen", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Exit element zapper mode", + "message": "Keluar daripada mod pemadam elemen", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "Buat penapis tersuai", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "Alih keluar penapis tersuai", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { - "message": "View:", + "message": "Lihat:", "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "Butiran mod penapisan", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "Peraturan DNR tersuai", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "Peraturan DNR bagi …", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "Set peraturan dinamik", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "Set peraturan sesi", "description": "An option in a dropdown list" }, "saveButton": { - "message": "Save", + "message": "Simpan", "description": "Text for buttons used to save changes" }, "revertButton": { - "message": "Revert", + "message": "Kembalikan", "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "Add", + "message": "Tambah", "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Import and append…", + "message": "Import dan lampirkan…", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Export…", + "message": "Eksport…", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "Sandarkan…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "Pulihkan…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "Tetapkan semula ke tetapan lalai…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "Semua tetapan tersuai anda akan dialih keluar. Adakah anda benar-benar ingin menetapkan semula ke tetapan lalai?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "Jangan tambah kandungan daripada sumber yang tidak dipercayai", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "Bilangan peraturan yang didaftarkan: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "Gerakkan peluncur untuk memilih padanan terbaik", "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Pick", + "message": "Pilih", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "Pratonton", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "Cipta", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "Pilih penapis di bawah untuk menyerlahkan elemen yang sepadan dalam laman web. Klik tong sampah untuk mengalih keluar penapis.", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/nb/messages.json b/platform/mv3/extension/_locales/nb/messages.json index f412787c39e56..59bf6ef199ab1 100644 --- a/platform/mv3/extension/_locales/nb/messages.json +++ b/platform/mv3/extension/_locales/nb/messages.json @@ -35,6 +35,10 @@ "message": "Personvernpraksis", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Dokumentasjon", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "filtreringsmodus", "description": "Label in the popup panel for the current filtering mode" @@ -87,6 +91,22 @@ "message": "Regioner, språk", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Importerte lister", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Legg til filterlister…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL of the filter list to add", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Importér/Eksportér", "description": "Text label heading the import/export area of custom filters" @@ -95,6 +115,10 @@ "message": "Lim inn her spesifikke kosmetiske filtre som skal legges til", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Open your browser's extensions page (chrome://extensions in Chrome or about:addons in Firefox), open uBO Lite details, and toggle on Allow user scripts (also referred to as “unverified third-party scripts”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Endringslogg", "description": "" @@ -255,12 +279,28 @@ "message": "Navigering til potensielt uønskede nettsteder blir blokkert, og du får tilbud om å fortsette.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Aktiver popup-blokkering", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Når denne er aktiv vil matchende filtre automatisk lukke uønskede nettleserfaner laget av nettsiden.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Filter-creation sandbox", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Utviklermodus", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Aktiver tilgang til funksjoner som er egnet for tekniske brukere.", + "message": "Aktiverer tilgang til funksjoner som er egnet for tekniske brukere.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { @@ -268,11 +308,11 @@ "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Sikkerhetskopier dine egendefinerte regler, eller gjenopprett dine egendefinerte regler fra en fil.", + "message": "Sikkerhetskopier dine egendefinerte innstillinger til en fil, eller gjenopprett dine egendefinerte innstillinger fra en fil.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Gjenoppretting vil overskrive dine nåværende egendefinerte regler.", + "message": "Gjenoppretting vil overskrive dine nåværende egendefinerte innstillinger.", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { @@ -316,7 +356,7 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Gå til element­fjernings­modus", + "message": "Fjern et element", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { @@ -368,11 +408,11 @@ "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Importer og legg til...", + "message": "Importer og legg til…", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Eksporter...", + "message": "Eksporter…", "description": "Text for buttons used to export content" }, "backupButton": { @@ -388,7 +428,7 @@ "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "Alle dine egendefinerte innstillinger vil bli fjernet. Vil du virkelig tilbakestille til standardinnstillingene?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { diff --git a/platform/mv3/extension/_locales/nl/messages.json b/platform/mv3/extension/_locales/nl/messages.json index c7e4f8d5640b7..37fc31c631a90 100644 --- a/platform/mv3/extension/_locales/nl/messages.json +++ b/platform/mv3/extension/_locales/nl/messages.json @@ -35,6 +35,10 @@ "message": "Privacybeleid", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Documentatie", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "filtermodus", "description": "Label in the popup panel for the current filtering mode" @@ -87,14 +91,34 @@ "message": "Gebieden, talen", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Geïmporteerde lijsten", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Filterlijst toevoegen…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL van de toe te voegen filterlijst", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "Om cosmetische of scriptletfilters vanuit geïmporteerde lijsten toe te passen, moet u uBO Lite toestemming geven voor het uitvoeren van gebruikersscripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Importeren / Exporteren", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Plak hier specifieke cosmetische of scriptletfilters om toe te voegen.", + "message": "Specifieke cosmetische of scriptletfilters om toe te voegen", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Open de extensiespagina van uw browser (chrome://extensions in Chrome of about:addons in Firefox), open de details van uBO Lite, en schakel Gebruikersscripts toestaan (ook wel aangeduid als ‘Niet-geverifieerde scripts van derden’) in.", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Wijzigingenlogboek", "description": "" @@ -228,7 +252,7 @@ "description": "This describes the 'complete' filtering mode" }, "noFilteringModeDescription": { - "message": "Lijst van hostnamen waarvoor geen filtering plaatsvindt.", + "message": "Lijst van websites waarvoor geen filtering plaatsvindt.", "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { @@ -255,6 +279,22 @@ "message": "Navigatie naar mogelijk ongewenste websites wordt geblokkeerd, en u krijgt de mogelijkheid om door te gaan.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Pop-upblokkering inschakelen", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Wanneer actief, sluiten overeenkomende filters automatisch ongewenste browsertabbladen die door websites zijn aangemaakt.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Sandbox voor het aanmaken van filters", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "Om cosmetische of scriptletfilters vanuit de sandbox toe te passen, moet u uBO Lite toestemming geven voor het uitvoeren van gebruikersscripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Ontwikkelaarsmodus", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/oc/messages.json b/platform/mv3/extension/_locales/oc/messages.json index 881b780e38fa2..0f924a6ef94e3 100644 --- a/platform/mv3/extension/_locales/oc/messages.json +++ b/platform/mv3/extension/_locales/oc/messages.json @@ -4,103 +4,127 @@ "description": "extension name." }, "extShortDesc": { - "message": "An efficient content blocker. Blocks ads, trackers, miners, and more immediately upon installation.", + "message": "Un blocaire de contengut eficient. Bloca las publicitats, los traçaires, los minaires, e mai, immediatament après l'installacion.", "description": "this will be in the Chrome web store: must be 132 characters or less" }, "perRulesetStats": { - "message": "{{ruleCount}} rules, converted from {{filterCount}} network filters", + "message": "{{ruleCount}} règlas, convertits dempuèi {{filterCount}} filtres ret", "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "dashboardName": { - "message": "uBO Lite — Dashboard", + "message": "uBO Lite — Tablèu de bòrd", "description": "English: uBO Lite — Dashboard" }, "settingsPageName": { - "message": "Settings", + "message": "Paramètres", "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "Custom filters", + "message": "Filtres personalizats", "description": "appears as tab name in dashboard" }, "developPageName": { - "message": "Develop", + "message": "Desvolopar", "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { - "message": "About", + "message": "A prepaus", "description": "appears as tab name in dashboard" }, "aboutPrivacyPolicy": { - "message": "Privacy policy", + "message": "Politica de confidencialitat", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Documentacion", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { - "message": "filtering mode", + "message": "mòde de filtratge", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "On this website", + "message": "Sus aqueste site web", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "Report an issue", + "message": "Senhalar un problèma", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { - "message": "Open the dashboard", + "message": "Dobrir lo tablèu de bòrd", "description": "English: Click to open the dashboard" }, "popupMoreButton": { - "message": "More", + "message": "Mai", "description": "Label to be used to show popup panel sections" }, "popupLessButton": { - "message": "Less", + "message": "Mens", "description": "Label to be used to hide popup panel sections" }, "3pGroupDefault": { - "message": "Default", + "message": "Per defaut", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAds": { - "message": "Ads", + "message": "Publicitats", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupPrivacy": { - "message": "Privacy", + "message": "Confidencialitat", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Malware protection, security", + "message": "Proteccion dels malware, seguretat", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { - "message": "Annoyances", + "message": "Nusenças", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMisc": { - "message": "Miscellaneous", + "message": "Divers", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupRegions": { - "message": "Regions, languages", + "message": "Regions, lengas", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "3pGroupImported": { + "message": "Listas importadas", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "customListImportLabel": { + "message": "Apondre una lista de filtres…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL de la lista de filtres d'apondre", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { - "message": "Import / Export", + "message": "Importar / Exportar", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "Filtres cosmetics/scriptlets especifics d'apondre", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Dobrissètz la pagina de las extensions de vòstre navigador (chrome://extensions dins Chrome o about:addons dins Firefox), dobrissètz los detalhs de uBO Lite, e activatz Permetre los scripts utilizaire (tanben nomenats “scripts tèrces pas verificats”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { - "message": "Changelog", + "message": "Jornal dels cambiaments", "description": "" }, "aboutCode": { - "message": "Source code (GPLv3)", + "message": "Còdi font (GPLv3)", "description": "English: Source code (GPLv3)" }, "aboutContributors": { @@ -108,99 +132,99 @@ "description": "English: Contributors" }, "aboutSourceCode": { - "message": "Source code", + "message": "Còdi font", "description": "Link text to source code repo" }, "aboutTranslations": { - "message": "Translations", + "message": "Traduccions", "description": "Link text to translations repo" }, "aboutFilterLists": { - "message": "Filter lists", + "message": "Listas de filtres", "description": "Link text to uBO's own filter lists repo" }, "aboutDependencies": { - "message": "External dependencies (GPLv3-compatible):", + "message": "Dependéncias extèrnas (compatiblas GPLv3):", "description": "Shown in the About pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "Senhalar un problèma de filtre", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "Senhalar los problèmas de filtres amb de sites web especifics al seguidor de problèmas uBlockOrigin/uAssets. Require un compte GitHub.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting information", + "message": "Informacions de diagnostic", "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "Per evitar de cargar los volontaris amb de rapòrts dobles, verificatz que lo problèma a pas ja estat senhalat. Nòta: clicar sul boton enviarà l'origina de la pagina a GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "Trobar de rapòrts semblables sus GitHub", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "Adreça de la pagina web:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "La pagina web…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- Causir una entrada --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "Aficha de publicitats o de rèstas de publicitat", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "A de subrecobriments o d'autras nusenças", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBO Lite", + "message": "Detecta uBO Lite", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "A de problèmas ligats a la confidencialitat", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBO Lite is enabled", + "message": "Malaise quand uBO Lite es activat", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "Dobrís d'onglets o de fenèstras pas desirats", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "Mena a de logicials malhèsts, phishing", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "Marcar la pagina web coma “NSFW” (“Pas segur pel trabalh”)", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "Crear un novèl rapòrt sus GitHub", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { - "message": "Default filtering mode", + "message": "Mòde de filtratge per defaut", "description": "The header text for the default filtering mode section" }, "defaultFilteringModeDescription": { - "message": "The default filtering mode will be overridden by per-website filtering modes. You can adjust the filtering mode on any given website according to whichever mode works best on that website. Each mode has its advantages and disadvantages.", + "message": "Lo mòde de filtratge per defaut serà anullat pels mòdes de filtratge per site. Podètz ajustar lo mòde de filtratge sus cada site segon lo mòde que fonciona melhor. Cada mòde a sos avantatges e sos desavantatges.", "description": "This describes the default filtering mode setting" }, "filteringMode0Name": { - "message": "no filtering", + "message": "pas de filtratge", "description": "Name of blocking mode 0" }, "filteringMode1Name": { @@ -212,211 +236,227 @@ "description": "Name of blocking mode 2" }, "filteringMode3Name": { - "message": "complete", + "message": "complet", "description": "Name of blocking mode 3" }, "basicFilteringModeDescription": { - "message": "Basic network filtering from selected filter lists.\n\nDoes not require permission to read and modify data on websites.", + "message": "Filtratge ret basic dempuèi las listas de filtres seleccionadas.\n\nRequire pas de permission per legir e modificar las donadas sus los sites web.", "description": "This describes the 'basic' filtering mode" }, "optimalFilteringModeDescription": { - "message": "Advanced network filtering plus specific extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.", + "message": "Filtratge ret avançat mai filtratge estendut especific dempuèi las listas de filtres seleccionadas.\n\nRequire una permission larga per legir e modificar las donadas sus totes los sites web.", "description": "This describes the 'optimal' filtering mode" }, "completeFilteringModeDescription": { - "message": "Advanced network filtering plus specific and generic extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.\n\nGeneric extended filtering may cause higher web page resources usage.", + "message": "Filtratge ret avançat mai filtratge estendut especific e generic dempuèi las listas de filtres seleccionadas.\n\nRequire una permission larga per legir e modificar las donadas sus totes los sites web.\n\nLo filtratge estendut generic pòt causar una utilizacion de ressorsas de pagina web mai nauta.", "description": "This describes the 'complete' filtering mode" }, "noFilteringModeDescription": { - "message": "List of websites for which no filtering will take place.", + "message": "Lista dels sites web per los quals cap de filtratge se debanarà.", "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { - "message": "[hostnames only]\nexample.com\ngames.example\n...", + "message": "[solament noms d'òste]\nexample.com\ngames.example\n...", "description": "Default text for in edit field" }, "behaviorSectionLabel": { - "message": "Behavior", + "message": "Comportament", "description": "The header text for the 'Behavior' section" }, "autoReloadLabel": { - "message": "Automatically reload page when changing filtering mode", + "message": "Recargar automaticament la pagina en cambiant de mòde de filtratge", "description": "Label for a checkbox in the options page" }, "showBlockedCountLabel": { - "message": "Show the number of blocked requests on the toolbar icon", + "message": "Afichar lo nombre de requèstas blocadas sus l'icòna de la barra d'aisinas", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "Enable strict blocking", + "message": "Activar lo blocatge estricte", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "La navigacion cap a de sites potencialament indesirables serà blocada, e vos serà prepausada l'opcion de contunhar.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Activar lo blocatge de las fenèstras sorgissents", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Quand es actiu, los filtres correspondents tamparàn automaticament los onglets de navigador pas desirats creats pels sites web.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Bac de sable de creacion de filtres", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Developer mode", + "message": "Mòde desvolopaire", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "Permet l'accès a de foncionalitats adaptadas als utilizaires tecnics.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "Salvagarda", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "Salvar vòstres paramètres personalizats dins un fichièr, o restaurar los dempuèi un fichièr.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "Restaurar subrescríserà totes vòstres paramètres personalizats actuals.", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "Find lists", + "message": "Trobar de listas", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { - "message": "Page blocked", + "message": "Pagina blocada", "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite has prevented the following page from loading:", + "message": "uBO Lite a empachat la pagina seguenta de se cargar:", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "The page was blocked because of a matching filter in {{listname}}.", + "message": "La pagina es estada blocada a causa d'un filtre correspondent dins {{listname}}.", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "La pagina blocada vòl redirigir cap a un autre site. Se causissètz de contunhar, naviguaretz dirèctament cap a: {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { - "message": "without parameters", + "message": "sens paramètres", "description": "Label to be used for the parameter-less URL" }, "strictblockBack": { - "message": "Go back", + "message": "Tornar", "description": "A button to go back to the previous web page" }, "strictblockClose": { - "message": "Close this window", + "message": "Tampar aquesta fenèstra", "description": "A button to close the current tab" }, "strictblockDontWarn": { - "message": "Don't warn me again about this site", + "message": "Me prevenir pas mai per aqueste site", "description": "Label for checkbox in document-blocked page" }, "strictblockProceed": { - "message": "Proceed", + "message": "Contunhar", "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Remove an element", + "message": "Suprimir un element", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Exit element zapper mode", + "message": "Sortir del mòde zappaire d'elements", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "Crear un filtre personalizat", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "Suprimir un filtre personalizat", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { - "message": "View:", + "message": "Veire:", "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "Detalhs del mòde de filtratge", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "Règlas DNR personalizadas", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "Règlas DNR de …", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "Jòc de règlas dinamic", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "Jòc de règlas de session", "description": "An option in a dropdown list" }, "saveButton": { - "message": "Save", + "message": "Salvar", "description": "Text for buttons used to save changes" }, "revertButton": { - "message": "Revert", + "message": "Anullar", "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "Add", + "message": "Apondre", "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Import and append…", + "message": "Importar e apondre…", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Export…", + "message": "Exportar…", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "Salvar…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "Restaurar…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "Reïnicializar als paramètres per defaut…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "Totes vòstres paramètres personalizats seràn suprimits. Volètz vertadièrament reïnicializar als paramètres per defaut?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "Non apondre de contengut de fonts pas fisablas", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "Nombre de règlas enregistradas: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "Desplaçar lo cursor per seleccionar la melhora correspondéncia", "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Pick", + "message": "Seleccionar", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "Previsualizar", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "Crear", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "Seleccionar un filtre çai-jos per metre en relèu los elements correspondents dins la pagina web. Clicar sus la corbèla per suprimir un filtre.", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/pa/messages.json b/platform/mv3/extension/_locales/pa/messages.json index d3a421c96a924..3c5de53eedc7e 100644 --- a/platform/mv3/extension/_locales/pa/messages.json +++ b/platform/mv3/extension/_locales/pa/messages.json @@ -35,6 +35,10 @@ "message": "ਪਰਦੇਦਾਰੀ ਨੀਤੀ", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "ਦਸਤਾਵੇਜ਼", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "ਫਿਲਟਰ ਕਰਨ ਦਾ ਮੋਡ", "description": "Label in the popup panel for the current filtering mode" @@ -87,14 +91,34 @@ "message": "ਖੇਤਰ, ਭਾਸ਼ਾਵਾਂ", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "ਇੰਪੋਰਟ ਕੀਤੀਆਂ ਸੂਚੀਆਂ", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "…ਫਿਲਟਰ ਸੂਚੀ ਜੋੜੋ", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "ਜੋੜਨ ਲਈ ਫਿਲਟਰ ਸੂਚੀ ਦਾ URL", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "ਇੰਪੋਰਟ / ਐਕਸਪੋਰਟ", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "ਜੋੜਨ ਲਈ ਖਾਸ ਕਾਸਮੈਟਿਕ/ਸਕ੍ਰਿਪਟਲੈੱਟ ਫਿਲਟਰ", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "ਆਪਣੇ ਬ੍ਰਾਊਜ਼ਰ ਦਾ ਐਕਸਟੈਂਸ਼ਨ ਪੰਨਾ ਖੋਲ੍ਹੋ (chrome://extensions Chrome ਵਿੱਚ ਜਾਂ about:addons Firefox ਵਿੱਚ), uBO Lite ਵੇਰਵੇ ਖੋਲ੍ਹੋ, ਅਤੇ Allow user scripts (ਜਿਸਨੂੰ “ਅਣਪ੍ਰਮਾਣਿਤ ਤੀਜੀ-ਧਿਰ ਸਕ੍ਰਿਪਟਾਂ” ਵੀ ਕਿਹਾ ਜਾਂਦਾ ਹੈ) ਨੂੰ ਚਾਲੂ ਕਰੋ।", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "ਤਬਦੀਲੀ-ਸੂਚੀ", "description": "" @@ -128,7 +152,7 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "ਖਾਸ ਵੈੱਬਸਾਈਟਾਂ ਨਾਲ ਫਿਲਟਰ ਸਮੱਸਿਆਵਾਂ ਦੀ ਰਿਪੋਰਟ uBlockOrigin/uAssets ਇਸ਼ੂ ਟਰੈਕਰ ਨੂੰ ਕਰੋ। ਇੱਕ GitHub ਖਾਤੇ ਦੀ ਲੋੜ ਹੈ।", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { @@ -136,7 +160,7 @@ "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "ਵਾਲੰਟੀਅਰਾਂ ਨੂੰ ਡੁਪਲੀਕੇਟ ਰਿਪੋਰਟਾਂ ਨਾਲ ਬੋਝ ਪਾਉਣ ਤੋਂ ਬਚਣ ਲਈ, ਕਿਰਪਾ ਕਰਕੇ ਪੁਸ਼ਟੀ ਕਰੋ ਕਿ ਇਸ ਸਮੱਸਿਆ ਦੀ ਰਿਪੋਰਟ ਪਹਿਲਾਂ ਤੋਂ ਨਹੀਂ ਕੀਤੀ ਗਈ ਹੈ। ਨੋਟ: ਬਟਨ 'ਤੇ ਕਲਿੱਕ ਕਰਨ ਨਾਲ ਪੰਨੇ ਦਾ ਮੂਲ GitHub ਨੂੰ ਭੇਜਿਆ ਜਾਵੇਗਾ।", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { @@ -160,7 +184,7 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "ਓਵਰਲੇ ਜਾਂ ਹੋਰ ਪਰੇਸ਼ਾਨੀਆਂ ਹਨ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { @@ -172,7 +196,7 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBO Lite is enabled", + "message": "ਜਦੋਂ uBO Lite ਸਮਰੱਥ ਹੁੰਦਾ ਹੈ ਤਾਂ ਖਰਾਬੀ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { @@ -180,11 +204,11 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "ਬੈਡਵੇਅਰ, ਫਿਸ਼ਿੰਗ ਵੱਲ ਲੈ ਜਾਂਦਾ ਹੈ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "ਵੈੱਬ ਪੰਨੇ ਨੂੰ “NSFW” ਵਜੋਂ ਲੇਬਲ ਕਰੋ (“ਕੰਮ ਲਈ ਸੁਰੱਖਿਅਤ ਨਹੀਂ”)", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { @@ -252,15 +276,31 @@ "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "ਸੰਭਾਵੀ ਤੌਰ 'ਤੇ ਅਣਚਾਹੇ ਸਾਈਟਾਂ 'ਤੇ ਨੈਵੀਗੇਸ਼ਨ ਨੂੰ ਬਲੌਕ ਕੀਤਾ ਜਾਵੇਗਾ, ਅਤੇ ਤੁਹਾਨੂੰ ਅੱਗੇ ਵਧਣ ਦਾ ਵਿਕਲਪ ਦਿੱਤਾ ਜਾਵੇਗਾ।", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "ਪੌਪ-ਅੱਪ ਬਲਾਕਿੰਗ ਸਮਰੱਥ ਕਰੋ", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "ਜਦੋਂ ਸਰਗਰਮ ਹੁੰਦਾ ਹੈ, ਤਾਂ ਮੇਲ ਖਾਂਦੇ ਫਿਲਟਰ ਆਪਣੇ ਆਪ ਵੈੱਬਸਾਈਟਾਂ ਦੁਆਰਾ ਬਣਾਏ ਗਏ ਅਣਚਾਹੇ ਬ੍ਰਾਊਜ਼ਰ ਟੈਬਾਂ ਨੂੰ ਬੰਦ ਕਰ ਦੇਣਗੇ।", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "ਫਿਲਟਰ-ਨਿਰਮਾਣ ਸੈਂਡਬਾਕਸ", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "ਡਿਵੈਲਪਰ ਮੋਡ", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "ਤਕਨੀਕੀ ਉਪਭੋਗਤਾਵਾਂ ਲਈ ਢੁਕਵੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਤੱਕ ਪਹੁੰਚ ਨੂੰ ਸਮਰੱਥ ਬਣਾਉਂਦਾ ਹੈ।", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { @@ -268,11 +308,11 @@ "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "ਆਪਣੀਆਂ ਕਸਟਮ ਸੈਟਿੰਗਾਂ ਨੂੰ ਇੱਕ ਫਾਈਲ ਵਿੱਚ ਬੈਕਅੱਪ ਕਰੋ, ਜਾਂ ਆਪਣੀਆਂ ਕਸਟਮ ਸੈਟਿੰਗਾਂ ਨੂੰ ਇੱਕ ਫਾਈਲ ਤੋਂ ਰੀਸਟੋਰ ਕਰੋ।", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "ਰੀਸਟੋਰ ਕਰਨ ਨਾਲ ਤੁਹਾਡੀਆਂ ਸਾਰੀਆਂ ਮੌਜੂਦਾ ਕਸਟਮ ਸੈਟਿੰਗਾਂ ਓਵਰਰਾਈਟ ਹੋ ਜਾਣਗੀਆਂ।", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { @@ -288,11 +328,11 @@ "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "The page was blocked because of a matching filter in {{listname}}.", + "message": "ਪੰਨਾ {{listname}} ਵਿੱਚ ਇੱਕ ਮੇਲ ਖਾਂਦੇ ਫਿਲਟਰ ਕਾਰਨ ਬਲੌਕ ਕੀਤਾ ਗਿਆ ਸੀ।", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "ਬਲੌਕ ਕੀਤਾ ਪੰਨਾ ਕਿਸੇ ਹੋਰ ਸਾਈਟ 'ਤੇ ਰੀਡਾਇਰੈਕਟ ਕਰਨਾ ਚਾਹੁੰਦਾ ਹੈ। ਜੇਕਰ ਤੁਸੀਂ ਅੱਗੇ ਵਧਣਾ ਚੁਣਦੇ ਹੋ, ਤਾਂ ਤੁਸੀਂ ਸਿੱਧੇ ਇਸ 'ਤੇ ਨੈਵੀਗੇਟ ਕਰੋਗੇ: {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { @@ -320,7 +360,7 @@ "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Exit element zapper mode", + "message": "ਐਲੀਮੈਂਟ ਜੈਪਰ ਮੋਡ ਤੋਂ ਬਾਹਰ ਨਿਕਲੋ", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { @@ -336,11 +376,11 @@ "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "ਫਿਲਟਰਿੰਗ ਮੋਡ ਵੇਰਵੇ", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "ਕਸਟਮ DNR ਨਿਯਮ", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { @@ -348,11 +388,11 @@ "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "ਡਾਇਨਾਮਿਕ ਨਿਯਮ-ਸੈੱਟ", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "ਸੈਸ਼ਨ ਨਿਯਮ-ਸੈੱਟ", "description": "An option in a dropdown list" }, "saveButton": { @@ -384,11 +424,11 @@ "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "ਡਿਫੌਲਟ ਸੈਟਿੰਗਾਂ 'ਤੇ ਰੀਸੈਟ ਕਰੋ…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "ਤੁਹਾਡੀਆਂ ਸਾਰੀਆਂ ਕਸਟਮ ਸੈਟਿੰਗਾਂ ਹਟਾ ਦਿੱਤੀਆਂ ਜਾਣਗੀਆਂ। ਕੀ ਤੁਸੀਂ ਸੱਚਮੁੱਚ ਡਿਫੌਲਟ ਸੈਟਿੰਗਾਂ 'ਤੇ ਰੀਸੈਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { @@ -400,7 +440,7 @@ "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "ਸਭ ਤੋਂ ਵਧੀਆ ਮੈਚ ਚੁਣਨ ਲਈ ਸਲਾਈਡਰ ਨੂੰ ਘੁਮਾਓ", "description": "Label to describe the purpose of the slider" }, "pickerPick": { @@ -416,7 +456,7 @@ "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "ਵੈੱਬ ਪੰਨੇ ਵਿੱਚ ਮੇਲ ਖਾਂਦੇ ਤੱਤਾਂ ਨੂੰ ਉਜਾਗਰ ਕਰਨ ਲਈ ਹੇਠਾਂ ਇੱਕ ਫਿਲਟਰ ਚੁਣੋ। ਇੱਕ ਫਿਲਟਰ ਨੂੰ ਹਟਾਉਣ ਲਈ ਰੱਦੀ ਵਾਲੇ ਡੱਬੇ 'ਤੇ ਕਲਿੱਕ ਕਰੋ।", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/pl/messages.json b/platform/mv3/extension/_locales/pl/messages.json index 6e01dc23c7aa3..9b015ab654927 100644 --- a/platform/mv3/extension/_locales/pl/messages.json +++ b/platform/mv3/extension/_locales/pl/messages.json @@ -35,6 +35,10 @@ "message": "Polityka prywatności", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Dokumentacja", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "Tryb filtrowania", "description": "Label in the popup panel for the current filtering mode" @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Domeny ze złośliwym oprogramowaniem", + "message": "Ochrona przed złośliwym oprogramowaniem, bezpieczeństwo", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,6 +91,22 @@ "message": "Regiony, języki", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Listy importowane", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Dodaj listę filtrów…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Wklej tutaj adres URL listy filtrów, którą chcesz dodać", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "Aby wymusić stosowanie filtrów kosmetycznych lub skryptletów z importowanych list, należy przyznać uBO Lite uprawnienie do uruchamiania skryptów użytkownika.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Import i eksport", "description": "Text label heading the import/export area of custom filters" @@ -95,6 +115,10 @@ "message": "Wklej tutaj określone filtry kosmetyczne do dodania", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Otwórz stronę rozszerzeń przeglądarki (chrome://extensions w Chrome lub about:addons w Firefoksie), otwórz szczegóły uBO Lite i włącz opcję Zezwalaj na skrypty użytkownika (nazywane również „niezweryfikowanymi skryptami zewnętrzymi”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Informacje o wydaniu", "description": "" @@ -255,6 +279,22 @@ "message": "Nawigacja do potencjalnie niepożądanych witryn zostanie zablokowana i pojawi się opcja kontynuowania.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Włącz blokowanie wyskakujących okienek", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Po aktywacji pasujące filtry będą automatycznie zamykać niechciane karty przeglądarki utworzone przez witryny internetowe.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Piaskownica tworzenia filtrów", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "Aby wymusić stosowanie filtrów kosmetycznych lub skryptletów z piaskownicy, należy przyznać uBO Lite uprawnienie do uruchamiania skryptów użytkownika.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Tryb programisty", "description": "Label for a checkbox in the options page" @@ -316,7 +356,7 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Przejdź do trybu usuwania elementów", + "message": "Usuń element", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { diff --git a/platform/mv3/extension/_locales/pt_BR/messages.json b/platform/mv3/extension/_locales/pt_BR/messages.json index 570e7120d4973..2ab7c73752549 100644 --- a/platform/mv3/extension/_locales/pt_BR/messages.json +++ b/platform/mv3/extension/_locales/pt_BR/messages.json @@ -35,6 +35,10 @@ "message": "Política de privacidade", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Documentação", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "modo de filtragem", "description": "Label in the popup panel for the current filtering mode" @@ -87,6 +91,22 @@ "message": "Regiões, idiomas", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Listas importadas", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Adicionar lista de filtros…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Cole aqui o URL da lista de filtros que quer adicionar", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "Para aplicar os filtros cosméticos e de scripts das listas importadas, você deve conceder ao uBO Lite a permissão de executar scripts do usuário.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Importação e exportação", "description": "Text label heading the import/export area of custom filters" @@ -95,6 +115,10 @@ "message": "Cole filtros cosméticos específicos aqui para adicioná-los", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Abra a página de extensões do seu navegador (chrome://extensions no Chrome ou about:addons no Firefox), abra os detalhes do uBO Lite, e ative Permitir scripts de usuário (também referidos como \"scripts de terceiros não verificados\").", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Notas de lançamento", "description": "" @@ -255,6 +279,22 @@ "message": "A navegação para sites potencialmente indesejáveis ​​será bloqueada e você terá a opção de prosseguir.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Ativar bloqueio de pop-ups", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Quando ativado, os filtros correspondentes fecharão automaticamente as abas indesejadas do navegador criadas por sites.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Ambiente isolado para criação de filtros", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "Para aplicar os filtros cosméticos e de scripts dentro da sandbox, você deve conceder ao uBO Lite a permissão de executar scripts do usuário.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Modo de desenvolvedor", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/pt_PT/messages.json b/platform/mv3/extension/_locales/pt_PT/messages.json index 881a97938178e..a0c64456322dd 100644 --- a/platform/mv3/extension/_locales/pt_PT/messages.json +++ b/platform/mv3/extension/_locales/pt_PT/messages.json @@ -35,6 +35,10 @@ "message": "Política de privacidade", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Documentação", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "modo de filtragem", "description": "Label in the popup panel for the current filtering mode" @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Proteção contra malware, segurança", + "message": "Proteção contra malware e segurança", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,20 +91,40 @@ "message": "Regiões, idiomas", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Listas importadas", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Adicionar lista de filtros…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL da lista de filtros a adicionar", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "Para aplicar filtros cosméticos ou de scriptlet provenientes de listas importadas, tem de conceder ao uBO Lite permissão para executar scripts do utilizador.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Importar/Exportar", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Cole aqui filtros cosméticos específicos a adicionar", + "message": "Filtros cosméticos/de scriptlet específicos a adicionar", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Abra a página de extensões do seu navegador (chrome://extensions no Chrome ou about:addons no Firefox), abra os detalhes do uBO Lite e ative a opção Permitir scripts do utilizador (também designada por \"scripts de terceiros não verificados\").", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Registo de alterações", "description": "" }, "aboutCode": { - "message": "Código fonte (GPLv3)", + "message": "Código-fonte (GPLv3)", "description": "English: Source code (GPLv3)" }, "aboutContributors": { @@ -108,7 +132,7 @@ "description": "English: Contributors" }, "aboutSourceCode": { - "message": "Código fonte", + "message": "Código-fonte", "description": "Link text to source code repo" }, "aboutTranslations": { @@ -255,6 +279,22 @@ "message": "A navegação para sites potencialmente indesejáveis será bloqueada e ser-lhe-á dada a opção de proceder.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Ativar bloqueio de janelas pop-up", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Quando ativado, os filtros correspondentes fecharão automaticamente os separadores indesejados do navegador criados pelos websites.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Sandbox para criação de filtros", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "Para aplicar filtros cosméticos ou de scriptlet provenientes da sandbox, tem de conceder ao uBO Lite permissão para executar scripts do utilizador.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Modo de programador", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/ro/messages.json b/platform/mv3/extension/_locales/ro/messages.json index dde28eb985f69..6dd6863b3963a 100644 --- a/platform/mv3/extension/_locales/ro/messages.json +++ b/platform/mv3/extension/_locales/ro/messages.json @@ -35,6 +35,10 @@ "message": "Politică de confidențialitate", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Documentație", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "Mod de filtrare", "description": "Label in the popup panel for the current filtering mode" @@ -87,6 +91,22 @@ "message": "Regiuni, limbi", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Liste importate", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Adaugă listă de filtre…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL-ul listei de filtre de adăugat", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Importă / Exportă", "description": "Text label heading the import/export area of custom filters" @@ -95,6 +115,10 @@ "message": "Lipește aici filtre cosmetice specifice", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Deschide pagina de extensii a browserului tău (chrome://extensions în Chrome sau about:addons în Firefox), deschide detaliile uBO Lite și activează opțiunea Permite scripturile de utilizator (numite și „scripturi de la terți neverificate”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Jurnal de modificări", "description": "" @@ -136,11 +160,11 @@ "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "Pentru a evita încărcarea voluntarilor cu rapoarte duplicate, vă rugăm să verificați dacă problema nu a fost deja raportată.", + "message": "Pentru a evita suprasolicitarea voluntarilor, vă rugăm să verificați dacă această problemă nu a fost deja raportată. Notă: dacă faceți clic pe buton, originea paginii va fi trimisă către GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Găsiți rapoarte similare", + "message": "Găsește sesizări similare pe GitHub", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { @@ -188,7 +212,7 @@ "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Creează o nouă sesizare", + "message": "Creează o nouă sesizare pe GitHub", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { @@ -255,6 +279,22 @@ "message": "Navigarea către site-uri potențial nedorite va fi blocată și vi se va oferi opțiunea de a continua.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Activați blocarea ferestrelor pop-up", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Când sunt active, filtrele potrivite vor închide automat filele nedorite de browser create de site-uri web.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Spațiu de testare pentru filtre", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Mod dezvoltator", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/ru/messages.json b/platform/mv3/extension/_locales/ru/messages.json index 79c04f5634e18..91a75e429ba84 100644 --- a/platform/mv3/extension/_locales/ru/messages.json +++ b/platform/mv3/extension/_locales/ru/messages.json @@ -35,6 +35,10 @@ "message": "Политика конфиденциальности", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Документация", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "режим фильтрации", "description": "Label in the popup panel for the current filtering mode" @@ -87,14 +91,34 @@ "message": "Регионы, языки", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Импортированные списки", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Добавить список фильтров…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL-адрес списка фильтров для добавления", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "Чтобы применять косметические фильтры или скриптлеты из импортированных списков, необходимо предоставить uBO Lite разрешение на выполнение пользовательских скриптов.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Импорт / Экспорт", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Вставьте сюда отдельные косметические фильтры/скриптлеты для добавления", + "message": "Вставьте косметические фильтры/скриптлеты для добавления", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Откройте страницу расширений вашего браузера (chrome://extensions в Chrome или about:addons в Firefox), откройте uBO Lite и включите Разрешить пользовательские скрипты (так называемые «непроверенные сторонние скрипты»).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Список изменений", "description": "" @@ -255,6 +279,22 @@ "message": "Переход к потенциально нежелательным сайтам будет заблокирован, и будет дана возможность продолжить переход на сайт", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Включить блокировку всплывающих окон", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Если активно, то подходящие фильтры будут автоматически закрывать нежелательные вкладки браузера, создаваемые веб-сайтами.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Песочница для создания фильтров", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "Чтобы применять косметические фильтры или скриптлеты из песочницы, необходимо предоставить uBO Lite разрешение на выполнение пользовательских скриптов.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Режим разработчика", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/si/messages.json b/platform/mv3/extension/_locales/si/messages.json index a29ea9027b6ae..9f33c06fdf743 100644 --- a/platform/mv3/extension/_locales/si/messages.json +++ b/platform/mv3/extension/_locales/si/messages.json @@ -20,11 +20,11 @@ "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "Custom filters", + "message": "අභිරුචි පෙරහන්", "description": "appears as tab name in dashboard" }, "developPageName": { - "message": "Develop", + "message": "සංවර්ධනය", "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { @@ -35,12 +35,16 @@ "message": "රහස්‍යතා ප්‍රතිපත්තිය", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "ප්‍රලේඛනය", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "පෙරීමේ ප්‍රකාරය", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "On this website", + "message": "මෙම වෙබ් අඩවිය මත", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { @@ -87,14 +91,34 @@ "message": "කලාපීය, භාෂා", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "ආයාත කළ ලැයිස්තු", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "පෙරහන් ලැයිස්තුව එක් කරන්න…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "එක් කළ යුතු පෙරහන් ලැයිස්තුවේ URL", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { - "message": "Import / Export", + "message": "ආයාත කරන්න / නිර්යාත කරන්න", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "එක් කළ යුතු විශේෂිත ආලේපන/ස්ක්‍රිප්ට්ලට් පෙරහන්", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "ඔබගේ බ්‍රවුසරයේ දිගු පිටුව විවෘත කරන්න (Chrome හි chrome://extensions හෝ Firefox හි about:addons), uBO Lite විස්තර විවෘත කරන්න, සහ පරිශීලක ස්ක්‍රිප්ට් වලට ඉඩ දෙන්න (එය “සත්‍යාපනය නොකළ තෙවන පාර්ශවීය ස්ක්‍රිප්ට්” ලෙසද හැඳින්වේ) සක්‍රිය කරන්න.", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "වෙනස්කම් සටහන", "description": "" @@ -255,24 +279,40 @@ "message": "අනවශ්‍ය විය හැකි අඩවි වෙත සංචාලනය අවහිර කරනු ලබන අතර, ඉදිරියට යාමට ඔබට විකල්පය ලබා දෙනු ඇත.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "පොප්-අප් අවහිර කිරීම සක්‍රිය කරන්න", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "සක්‍රිය විට, ගැලපෙන පෙරහන් වෙබ් අඩවි මගින් සාදන ලද අනවශ්‍ය බ්‍රවුසර පටිත්ත ස්වයංක්‍රීයව වසා දමනු ඇත.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "පෙරහන්-නිර්මාණ වැලිපිල්ල", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Developer mode", + "message": "සංවර්ධක ප්‍රකාරය", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "තාක්ෂණික පරිශීලකයින් සඳහා සුදුසු විශේෂාංග වෙත ප්‍රවේශය සක්‍රිය කරයි.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "උපස්ථය", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "ඔබගේ අභිරුචි සැකසුම් ගොනුවකට උපස්ථ කරන්න, හෝ ගොනුවකින් ඔබගේ අභිරුචි සැකසුම් ප්‍රතිසාධනය කරන්න.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "ප්‍රතිසාධනය කිරීම ඔබගේ සියලු වත්මන් අභිරුචි සැකසුම් උඩින් ලියනු ඇත.", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { @@ -316,7 +356,7 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "මූලද්‍රව්‍ය zapper ප්‍රකාරයට ඇතුළු වන්න", + "message": "මූලද්‍රව්‍යයක් ඉවත් කරන්න", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { @@ -324,99 +364,99 @@ "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "අභිරුචි පෙරහනක් සාදන්න", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "අභිරුචි පෙරහනක් ඉවත් කරන්න", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { - "message": "View:", + "message": "දර්ශනය:", "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "පෙරීමේ ප්‍රකාරය විස්තර", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "අභිරුචි DNR නීති", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "... හි DNR නීති", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "ගතික නීති කට්ටලය", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "සැසි නීති කට්ටලය", "description": "An option in a dropdown list" }, "saveButton": { - "message": "Save", + "message": "සුරකින්න", "description": "Text for buttons used to save changes" }, "revertButton": { - "message": "Revert", + "message": "නැවත පෙර තත්වයට", "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "Add", + "message": "එක් කරන්න", "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Import and append…", + "message": "ආයාත කර අමුණන්න…", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Export…", + "message": "නිර්යාත කරන්න…", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "උපස්ථ කරන්න…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "ප්‍රතිසාධනය කරන්න…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "පෙරනිමි සැකසුම් වලට නැවත සකසන්න…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "ඔබගේ සියලු අභිරුචි සැකසුම් ඉවත් කරනු ඇත. ඔබට සැබවින්ම පෙරනිමි සැකසුම් වලට නැවත සැකසීමට අවශ්‍යද?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "විශ්වාස කළ නොහැකි මූලාශ්‍ර වලින් අන්තර්ගතය එක් නොකරන්න", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "ලියාපදිංචි කළ නීති ගණන: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "හොඳම ගැලපීම තෝරා ගැනීමට ස්ලයිඩරය ගෙන යන්න", "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Pick", + "message": "තෝරන්න", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "පෙරදසුන", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "සාදන්න", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "වෙබ් පිටුවේ ගැලපෙන මූලද්‍රව්‍ය උද්දීපනය කිරීමට පහත පෙරහනක් තෝරන්න. පෙරහනක් ඉවත් කිරීමට කුණු කූඩය ක්ලික් කරන්න.", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/sk/messages.json b/platform/mv3/extension/_locales/sk/messages.json index cf607c853bf4b..18d594bbdaa04 100644 --- a/platform/mv3/extension/_locales/sk/messages.json +++ b/platform/mv3/extension/_locales/sk/messages.json @@ -35,6 +35,10 @@ "message": "Zásady ochrany osobných údajov", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Dokumentácia", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "Režim filtrovania", "description": "Label in the popup panel for the current filtering mode" @@ -87,6 +91,22 @@ "message": "Regióny, jazyky", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Importované zoznamy", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Pridať zoznam filtrov…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Sem vložte URL zoznamu filtrov, ktorý chcete pridať", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "Ak chcete uplatniť kozmetické filtre alebo scriptlety z importovaných zoznamov, musíte udeliť uBO Lite oprávnenie na spúšťanie používateľských skriptov.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Import/export", "description": "Text label heading the import/export area of custom filters" @@ -95,6 +115,10 @@ "message": "Sem vložte špecifické kozmetické filtre, ktoré chcete pridať", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Otvorte stránku s rozšíreniami v prehliadači (chrome://extensions v prehliadači Chrome alebo about:addons vo Firefoxe), otvorte podrobnosti o uBO Lite a zapnite možnosť Povoliť používateľské skripty (tiež označované ako \"neoverené skripty tretích strán\").", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Zoznam zmien", "description": "" @@ -255,6 +279,22 @@ "message": "Navigácia na potenciálne nežiaduce stránky sa zablokuje a ponúkne sa vám možnosť pokračovať.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Povoliť blokovanie vyskakovacích okien", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Ak je zapnuté, príslušné filtre automaticky zatvoria nepotrebné karty prehliadača, ktoré otvorili webové stránky.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Sandbox na vytváranie filtrov", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "Ak chcete uplatniť kozmetické filtre alebo scriptlety zo sandboxu, musíte udeliť uBO Lite oprávnenie na spúšťanie používateľských skriptov.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Vývojársky režim", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/sl/messages.json b/platform/mv3/extension/_locales/sl/messages.json index 881b780e38fa2..b97dd3f7d251d 100644 --- a/platform/mv3/extension/_locales/sl/messages.json +++ b/platform/mv3/extension/_locales/sl/messages.json @@ -4,419 +4,459 @@ "description": "extension name." }, "extShortDesc": { - "message": "An efficient content blocker. Blocks ads, trackers, miners, and more immediately upon installation.", + "message": "Učinkovit blokator vsebin. Takoj po namestitvi blokira oglase, sledilnike, rudarje in več.", "description": "this will be in the Chrome web store: must be 132 characters or less" }, "perRulesetStats": { - "message": "{{ruleCount}} rules, converted from {{filterCount}} network filters", + "message": "{{ruleCount}} pravil, pretvorjenih iz {{filterCount}} omrežnih filtrov", "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "dashboardName": { - "message": "uBO Lite — Dashboard", + "message": "uBO Lite — Nadzorna plošča", "description": "English: uBO Lite — Dashboard" }, "settingsPageName": { - "message": "Settings", + "message": "Nastavitve", "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "Custom filters", + "message": "Filtri po meri", "description": "appears as tab name in dashboard" }, "developPageName": { - "message": "Develop", + "message": "Razvoj", "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { - "message": "About", + "message": "O programu", "description": "appears as tab name in dashboard" }, "aboutPrivacyPolicy": { - "message": "Privacy policy", + "message": "Politika zasebnosti", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Dokumentacija", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { - "message": "filtering mode", + "message": "način filtriranja", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "On this website", + "message": "Na tem spletnem mestu", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "Report an issue", + "message": "Prijavi težavo", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { - "message": "Open the dashboard", + "message": "Odpri nadzorno ploščo", "description": "English: Click to open the dashboard" }, "popupMoreButton": { - "message": "More", + "message": "Več", "description": "Label to be used to show popup panel sections" }, "popupLessButton": { - "message": "Less", + "message": "Manj", "description": "Label to be used to hide popup panel sections" }, "3pGroupDefault": { - "message": "Default", + "message": "Privzeto", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAds": { - "message": "Ads", + "message": "Oglasi", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupPrivacy": { - "message": "Privacy", + "message": "Zasebnost", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Malware protection, security", + "message": "Zaščita pred zlonamerno programsko opremo, varnost", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { - "message": "Annoyances", + "message": "Nadloge", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMisc": { - "message": "Miscellaneous", + "message": "Razno", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupRegions": { - "message": "Regions, languages", + "message": "Regije, jeziki", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "3pGroupImported": { + "message": "Uvoženi seznami", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "customListImportLabel": { + "message": "Dodaj seznam filtrov…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL seznama filtrov za dodajanje", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { - "message": "Import / Export", + "message": "Uvozi / Izvozi", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "Specifični kozmetični/skriptletni filtri za dodajanje", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Odprite stran z razširitvami v brskalniku (chrome://extensions v Chromu ali about:addons v Firefoxu), odprite podrobnosti za uBO Lite in omogočite Dovoli uporabniške skripte (imenovane tudi “nepreverjene skripte tretjih oseb”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { - "message": "Changelog", + "message": "Dnevnik sprememb", "description": "" }, "aboutCode": { - "message": "Source code (GPLv3)", + "message": "Izvorna koda (GPLv3)", "description": "English: Source code (GPLv3)" }, "aboutContributors": { - "message": "Contributors", + "message": "Sodelavci", "description": "English: Contributors" }, "aboutSourceCode": { - "message": "Source code", + "message": "Izvorna koda", "description": "Link text to source code repo" }, "aboutTranslations": { - "message": "Translations", + "message": "Prevodi", "description": "Link text to translations repo" }, "aboutFilterLists": { - "message": "Filter lists", + "message": "Seznami filtrov", "description": "Link text to uBO's own filter lists repo" }, "aboutDependencies": { - "message": "External dependencies (GPLv3-compatible):", + "message": "Zunanje odvisnosti (združljive z GPLv3):", "description": "Shown in the About pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "Prijavi težavo s filtrom", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "Težave s filtri na določenih spletnih mestih prijavite na uBlockOrigin/uAssets sledilniku težav. Zahteva račun GitHub.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting information", + "message": "Informacije za odpravljanje težav", "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "Da ne bi obremenjevali prostovoljcev z dvojnimi poročili, preverite, ali težava še ni bila prijavljena. Opomba: s klikom na gumb se izvor strani pošlje na GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "Poišči podobna poročila na GitHubu", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "Naslov spletne strani:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "Spletna stran…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- Izberite vnos --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "Prikazuje oglase ali ostanke oglasov", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "Ima prekrivne elemente ali druge nadloge", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBO Lite", + "message": "Zazna uBO Lite", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "Ima težave, povezane z zasebnostjo", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBO Lite is enabled", + "message": "Ne deluje pravilno, ko je uBO Lite omogočen", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "Odpre neželene zavihke ali okna", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "Vodi do zlonamerne programske opreme, lažnega predstavljanja", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "Označi spletno stran kot “NSFW” (“Ni primerno za delo”)", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "Ustvari novo poročilo na GitHubu", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { - "message": "Default filtering mode", + "message": "Privzeti način filtriranja", "description": "The header text for the default filtering mode section" }, "defaultFilteringModeDescription": { - "message": "The default filtering mode will be overridden by per-website filtering modes. You can adjust the filtering mode on any given website according to whichever mode works best on that website. Each mode has its advantages and disadvantages.", + "message": "Privzeti način filtriranja bo prepisan z načini filtriranja za posamezna spletna mesta. Na katerem koli spletnem mestu lahko prilagodite način filtriranja glede na to, kateri način na tem mestu najbolje deluje. Vsak način ima svoje prednosti in slabosti.", "description": "This describes the default filtering mode setting" }, "filteringMode0Name": { - "message": "no filtering", + "message": "brez filtriranja", "description": "Name of blocking mode 0" }, "filteringMode1Name": { - "message": "basic", + "message": "osnovno", "description": "Name of blocking mode 1" }, "filteringMode2Name": { - "message": "optimal", + "message": "optimalno", "description": "Name of blocking mode 2" }, "filteringMode3Name": { - "message": "complete", + "message": "popolno", "description": "Name of blocking mode 3" }, "basicFilteringModeDescription": { - "message": "Basic network filtering from selected filter lists.\n\nDoes not require permission to read and modify data on websites.", + "message": "Osnovno omrežno filtriranje iz izbranih seznamov filtrov.\n\nNe zahteva dovoljenja za branje in spreminjanje podatkov na spletnih mestih.", "description": "This describes the 'basic' filtering mode" }, "optimalFilteringModeDescription": { - "message": "Advanced network filtering plus specific extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.", + "message": "Napredno omrežno filtriranje in specifično razširjeno filtriranje iz izbranih seznamov filtrov.\n\nZahteva široko dovoljenje za branje in spreminjanje podatkov na vseh spletnih mestih.", "description": "This describes the 'optimal' filtering mode" }, "completeFilteringModeDescription": { - "message": "Advanced network filtering plus specific and generic extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.\n\nGeneric extended filtering may cause higher web page resources usage.", + "message": "Napredno omrežno filtriranje ter specifično in generično razširjeno filtriranje iz izbranih seznamov filtrov.\n\nZahteva široko dovoljenje za branje in spreminjanje podatkov na vseh spletnih mestih.\n\nGenerično razširjeno filtriranje lahko povzroči večjo porabo virov spletne strani.", "description": "This describes the 'complete' filtering mode" }, "noFilteringModeDescription": { - "message": "List of websites for which no filtering will take place.", + "message": "Seznam spletnih mest, za katera filtriranje ne bo potekalo.", "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { - "message": "[hostnames only]\nexample.com\ngames.example\n...", + "message": "[samo imena gostiteljev]\nexample.com\ngames.example\n...", "description": "Default text for in edit field" }, "behaviorSectionLabel": { - "message": "Behavior", + "message": "Vedenje", "description": "The header text for the 'Behavior' section" }, "autoReloadLabel": { - "message": "Automatically reload page when changing filtering mode", + "message": "Ob spremembi načina filtriranja samodejno ponovno naloži stran", "description": "Label for a checkbox in the options page" }, "showBlockedCountLabel": { - "message": "Show the number of blocked requests on the toolbar icon", + "message": "Na ikoni orodne vrstice prikaži število blokiranih zahtevkov", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "Enable strict blocking", + "message": "Omogoči strogo blokiranje", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "Navigacija na potencialno nezaželena spletna mesta bo blokirana, ponujena pa vam bo možnost nadaljevanja.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Omogoči blokiranje pojavnih oken", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Ko je aktivno, bodo ustrezni filtri samodejno zaprli neželene zavihke brskalnika, ki jih ustvarijo spletna mesta.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Peskovnik za ustvarjanje filtrov", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Developer mode", + "message": "Razvojni način", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "Omogoča dostop do funkcij, primernih za tehnične uporabnike.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "Varnostno kopiranje", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "Varnostno kopirajte svoje nastavitve po meri v datoteko ali jih obnovite iz datoteke.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "Obnovitev bo prepisala vse vaše trenutne nastavitve po meri.", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "Find lists", + "message": "Poišči sezname", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { - "message": "Page blocked", + "message": "Stran blokirana", "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite has prevented the following page from loading:", + "message": "uBO Lite je preprečil nalaganje naslednje strani:", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "The page was blocked because of a matching filter in {{listname}}.", + "message": "Stran je bila blokirana zaradi ustreznega filtra v {{listname}}.", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "Blokirana stran želi preusmeriti na drugo spletno mesto. Če izberete nadaljevanje, boste neposredno preusmerjeni na: {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { - "message": "without parameters", + "message": "brez parametrov", "description": "Label to be used for the parameter-less URL" }, "strictblockBack": { - "message": "Go back", + "message": "Nazaj", "description": "A button to go back to the previous web page" }, "strictblockClose": { - "message": "Close this window", + "message": "Zapri to okno", "description": "A button to close the current tab" }, "strictblockDontWarn": { - "message": "Don't warn me again about this site", + "message": "Ne opozarjaj me več za to spletno mesto", "description": "Label for checkbox in document-blocked page" }, "strictblockProceed": { - "message": "Proceed", + "message": "Nadaljuj", "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Remove an element", + "message": "Odstrani element", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Exit element zapper mode", + "message": "Izhod iz načina odstranjevanja elementov", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "Ustvari filter po meri", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "Odstrani filter po meri", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { - "message": "View:", + "message": "Pogled:", "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "Podrobnosti načina filtriranja", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "Pravila DNR po meri", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "Pravila DNR za …", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "Dinamični sklop pravil", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "Sejni sklop pravil", "description": "An option in a dropdown list" }, "saveButton": { - "message": "Save", + "message": "Shrani", "description": "Text for buttons used to save changes" }, "revertButton": { - "message": "Revert", + "message": "Povrni", "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "Add", + "message": "Dodaj", "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Import and append…", + "message": "Uvozi in dodaj…", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Export…", + "message": "Izvozi…", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "Varnostno kopiraj…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "Obnovi…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "Ponastavi na privzete nastavitve…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "Vse vaše nastavitve po meri bodo odstranjene. Ali res želite ponastaviti na privzete nastavitve?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "Ne dodajajte vsebin iz nezaupanja vrednih virov", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "Število registriranih pravil: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "Premaknite drsnik, da izberete najboljše ujemanje", "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Pick", + "message": "Izberi", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "Predogled", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "Ustvari", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "Spodaj izberite filter, da označite ustrezne elemente na spletni strani. Kliknite koš za odstranitev filtra.", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/so/messages.json b/platform/mv3/extension/_locales/so/messages.json index 881b780e38fa2..df25f9db04036 100644 --- a/platform/mv3/extension/_locales/so/messages.json +++ b/platform/mv3/extension/_locales/so/messages.json @@ -4,11 +4,11 @@ "description": "extension name." }, "extShortDesc": { - "message": "An efficient content blocker. Blocks ads, trackers, miners, and more immediately upon installation.", + "message": "Xannibaade wax ku ool ah. Wuxuu xannibaa xayeysiisyo, raad-raacyo, macdan-qodeyaal, iyo waxyaabo kale isla marka la rakibo.", "description": "this will be in the Chrome web store: must be 132 characters or less" }, "perRulesetStats": { - "message": "{{ruleCount}} rules, converted from {{filterCount}} network filters", + "message": "{{ruleCount}} xeerar, oo laga beddelay {{filterCount}} shaandho shabakadeed", "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "dashboardName": { @@ -16,407 +16,447 @@ "description": "English: uBO Lite — Dashboard" }, "settingsPageName": { - "message": "Settings", + "message": "Dejinta", "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "Custom filters", + "message": "Shaandhooyin habaysan", "description": "appears as tab name in dashboard" }, "developPageName": { - "message": "Develop", + "message": "Horumar", "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { - "message": "About", + "message": "Ku saabsan", "description": "appears as tab name in dashboard" }, "aboutPrivacyPolicy": { - "message": "Privacy policy", + "message": "Siyaasadda gaar ahaaneed", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Dokumentasho", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { - "message": "filtering mode", + "message": "habka shaandhaynta", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "On this website", + "message": "Websaydhkan", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "Report an issue", + "message": "Soo sheeg dhibaato", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { - "message": "Open the dashboard", + "message": "Fur dashboard-ka", "description": "English: Click to open the dashboard" }, "popupMoreButton": { - "message": "More", + "message": "Dheeri ah", "description": "Label to be used to show popup panel sections" }, "popupLessButton": { - "message": "Less", + "message": "Ka yar", "description": "Label to be used to hide popup panel sections" }, "3pGroupDefault": { - "message": "Default", + "message": "Goobjoog", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAds": { - "message": "Ads", + "message": "Xayeysiis", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupPrivacy": { - "message": "Privacy", + "message": "Gaar ahaaneed", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Malware protection, security", + "message": "Ilaalinta Malware-ka, amniga", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { - "message": "Annoyances", + "message": "Waxyaabaha dhibka ah", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMisc": { - "message": "Miscellaneous", + "message": "Kala duwan", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupRegions": { - "message": "Regions, languages", + "message": "Gobollo, luqado", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "3pGroupImported": { + "message": "Liisasyo la soo dejisay", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "customListImportLabel": { + "message": "Ku dar liiska shaandhada…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL-ka liiska shaandhada ee la rabo in la daro", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { - "message": "Import / Export", + "message": "Soo dejinta / Dhoofinta", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "Shaandhooyin qurxin/qoraal-yar oo gaar ah oo la rabo in la daro", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Fur bogga kordhinta biraawsarkaaga (chrome://extensions Chrome ama about:addons Firefox), fur faahfaahinta uBO Lite, oo daawo Oggolow qoraallada isticmaalaha (oo sidoo kale loo yaqaan “qoraallada dhinac-saddexaad ee aan la xaqiijin”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { - "message": "Changelog", + "message": "Diiwaanka isbeddelka", "description": "" }, "aboutCode": { - "message": "Source code (GPLv3)", + "message": "Koodka isha (GPLv3)", "description": "English: Source code (GPLv3)" }, "aboutContributors": { - "message": "Contributors", + "message": "Ka-qaybgalayaasha", "description": "English: Contributors" }, "aboutSourceCode": { - "message": "Source code", + "message": "Koodka isha", "description": "Link text to source code repo" }, "aboutTranslations": { - "message": "Translations", + "message": "Turjumaadyo", "description": "Link text to translations repo" }, "aboutFilterLists": { - "message": "Filter lists", + "message": "Liisaska shaandhada", "description": "Link text to uBO's own filter lists repo" }, "aboutDependencies": { - "message": "External dependencies (GPLv3-compatible):", + "message": "Ku-tiirsanaanta dibadda (GPLv3-ku-waafaqsan):", "description": "Shown in the About pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "Soo sheeg dhibaatada shaandhada", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "Soo sheeg dhibaatooyinka shaandhada ee websaydhyada gaarka ah raad-raaciyaha dhibaatooyinka uBlockOrigin/uAssets. Waxay u baahan tahay akoon GitHub.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting information", + "message": "Macluumaadka cilad-baadhista", "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "Si looga fogaado in loola culeeyo mutadawiciinta warbixino isku mid ah, fadlan hubi in dhibaatada aan weli la soo sheegin. Fiiro gaar ah: gujinta batoomada waxay keenaysaa in asalka bogga loo diro GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "Raadi warbixino la mid ah oo ku yaal GitHub", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "Ciwaanka bogga websaydhka:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "Bogga websaydhka…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- Dooro gelin --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "Wuxuu muujiyaa xayeysiisyo ama hadhaagii xayeysiiska", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "Wuxuu leeyahay dahaar ama waxyaabo kale oo dhib badan", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBO Lite", + "message": "Wuxuu ogaadaa uBO Lite", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "Wuxuu leeyahay dhibaatooyin la xiriira gaar ahaaneed", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBO Lite is enabled", + "message": "Waxay cilladeeyaan marka uBO Lite la daayo", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "Wuxuu furayaa tabo ama daaqado aan la rabin", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "Wuxuu u horseedaa barnaamij xun, khiyaamo (phishing)", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "U calaamadee bogga websaydhka sida “NSFW” (“Aan Ammaan u ahayn Shaqada”)", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "Samee warbixin cusub oo ku taal GitHub", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { - "message": "Default filtering mode", + "message": "Habka shaandhaynta goobjoogga ah", "description": "The header text for the default filtering mode section" }, "defaultFilteringModeDescription": { - "message": "The default filtering mode will be overridden by per-website filtering modes. You can adjust the filtering mode on any given website according to whichever mode works best on that website. Each mode has its advantages and disadvantages.", + "message": "Habka shaandhaynta goobjoogga ah waxaa beddeli doona hababka shaandhaynta websaydh kasta. Waxaad ku hagaajin kartaa habka shaandhaynta websaydh kasta iyadoo loo eegayo habka ugu habboon websaydhkaas. Hab kasta wuxuu leeyahay faa'iidooyin iyo cillado.", "description": "This describes the default filtering mode setting" }, "filteringMode0Name": { - "message": "no filtering", + "message": "shaandhayn la'aan", "description": "Name of blocking mode 0" }, "filteringMode1Name": { - "message": "basic", + "message": "aasaasi", "description": "Name of blocking mode 1" }, "filteringMode2Name": { - "message": "optimal", + "message": "ugu habboon", "description": "Name of blocking mode 2" }, "filteringMode3Name": { - "message": "complete", + "message": "dhammaystiran", "description": "Name of blocking mode 3" }, "basicFilteringModeDescription": { - "message": "Basic network filtering from selected filter lists.\n\nDoes not require permission to read and modify data on websites.", + "message": "Shaandhayn shabakadeed oo aasaasi ah oo ka timid liisaska shaandhada ee la doortay.\n\nUma baahna ogolaansho si loo akhriyo oo loo beddelo xogta websaydhyada.", "description": "This describes the 'basic' filtering mode" }, "optimalFilteringModeDescription": { - "message": "Advanced network filtering plus specific extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.", + "message": "Shaandhayn shabakadeed oo horumarsan oo ay weheliso shaandhayn gaar ah oo la fidiyay oo ka timid liisaska shaandhada ee la doortay.\n\nWaxay u baahan tahay ogolaansho ballaaran si loo akhriyo oo loo beddelo xogta websaydhyada oo dhan.", "description": "This describes the 'optimal' filtering mode" }, "completeFilteringModeDescription": { - "message": "Advanced network filtering plus specific and generic extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.\n\nGeneric extended filtering may cause higher web page resources usage.", + "message": "Shaandhayn shabakadeed oo horumarsan oo ay weheliso shaandhayn gaar ah iyo mid guud oo la fidiyay oo ka timid liisaska shaandhada ee la doortay.\n\nWaxay u baahan tahay ogolaansho ballaaran si loo akhriyo oo loo beddelo xogta websaydhyada oo dhan.\n\nShaandhaynta la fidiyay ee guud waxay sababi kartaa isticmaalka kheyraadka bogga websaydhka oo kordha.", "description": "This describes the 'complete' filtering mode" }, "noFilteringModeDescription": { - "message": "List of websites for which no filtering will take place.", + "message": "Liiska websaydhyada aan shaandhayn ka dhici doonin.", "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { - "message": "[hostnames only]\nexample.com\ngames.example\n...", + "message": "[magacyo martigaliyayaal oo keliya]\nexample.com\ngames.example\n...", "description": "Default text for in edit field" }, "behaviorSectionLabel": { - "message": "Behavior", + "message": "Dabeecad", "description": "The header text for the 'Behavior' section" }, "autoReloadLabel": { - "message": "Automatically reload page when changing filtering mode", + "message": "Si toos ah dib u soo deji bogga marka la beddelo habka shaandhaynta", "description": "Label for a checkbox in the options page" }, "showBlockedCountLabel": { - "message": "Show the number of blocked requests on the toolbar icon", + "message": "Muuji tirada codsiyada la xannibay astaanta qalabka", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "Enable strict blocking", + "message": "Daawo xannibaad adag", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "Dhaadhaca websaydhyada suurtogalka ah ee aan la rabin waa la xannibi doonaa, waxaana la siin doonaa fursad aad ku sii waddo.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Daawo xannibaadda pop-up-ka", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Marka ay firfircoon tahay, shaandhooyinka u dhigma waxay si toos ah u xirayaan tabooyinka biraawsarka ee aan la rabin ee ay abuuraan websaydhyada.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Sanduuqa ciyaarta ee abuurista shaandhada", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Developer mode", + "message": "Habka horumariyaha", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "Waxay u oggolaanaysaa helitaanka astaamooyinka ku habboon isticmaaleyaasha farsamada yaqaaniin.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "Kayd", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "Ku kaydso dejintaada habaysan fayl, ama soo celi dejintaada habaysan fayl.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "Soo celintu waxay ku qori doontaa dhammaan dejintaada habaysan ee hadda jirta.", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "Find lists", + "message": "Raadi liisasyo", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { - "message": "Page blocked", + "message": "Bog la xannibay", "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite has prevented the following page from loading:", + "message": "uBO Lite ayaa ka hor istaagtay in boggan soo dego:", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "The page was blocked because of a matching filter in {{listname}}.", + "message": "Bogga waa la xannibay sababtoo ah shaandho u dhigma oo ku jirta {{listname}}.", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "Bogga la xannibay wuxuu rabaa inuu u wareego bog kale. Haddii aad doorato inaad sii waddo, waxaad si toos ah ugu dhaadhacdaa: {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { - "message": "without parameters", + "message": "iyadoo aan lahayn cabbirro", "description": "Label to be used for the parameter-less URL" }, "strictblockBack": { - "message": "Go back", + "message": "Dib u noqo", "description": "A button to go back to the previous web page" }, "strictblockClose": { - "message": "Close this window", + "message": "Xidh daaqaddan", "description": "A button to close the current tab" }, "strictblockDontWarn": { - "message": "Don't warn me again about this site", + "message": "Ha igu digin mar labaad oo ku saabsan boggan", "description": "Label for checkbox in document-blocked page" }, "strictblockProceed": { - "message": "Proceed", + "message": "Sii wad", "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Remove an element", + "message": "Ka saar qayb", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Exit element zapper mode", + "message": "Ka bax habka xaaqista qaybaha", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "Abuur shaandho habaysan", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "Ka saar shaandho habaysan", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { - "message": "View:", + "message": "Daawo:", "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "Faahfaahinta habka shaandhaynta", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "Xeerarka DNR ee habaysan", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "Xeerarka DNR ee …", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "Xeerar firfircoon", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "Xeerar kalfadhi", "description": "An option in a dropdown list" }, "saveButton": { - "message": "Save", + "message": "Kaydi", "description": "Text for buttons used to save changes" }, "revertButton": { - "message": "Revert", + "message": "Noqo", "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "Add", + "message": "Ku dar", "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Import and append…", + "message": "Soo dejiso oo ku dar…", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Export…", + "message": "Dhoofin…", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "Kaydso…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "Soo celi…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "Ku celi dejinta goobjoogga ah…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "Dhammaan dejintaada habaysan waa la saari doonaa. Runtii ma waxaad rabtaa inaad ku celiso dejinta goobjoogga ah?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "Ha ku darin waxyaabo ka yimid ilo aan la kalsooni karin", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "Tirada xeerarka la diiwaan geliyay: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "Dhaqaaji kala-rogaha si aad u doorato waxa ugu habboon", "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Pick", + "message": "Dooro", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "Horumuuji", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "Abuur", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "Dooro shaandho hoose si aad u iftiimiso qaybaha u dhigma ee bogga websaydhka. Guji qashinka si aad uga saarto shaandho.", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/sq/messages.json b/platform/mv3/extension/_locales/sq/messages.json index 66b5ca4eef6a6..dc67cbbd0d53d 100644 --- a/platform/mv3/extension/_locales/sq/messages.json +++ b/platform/mv3/extension/_locales/sq/messages.json @@ -35,6 +35,10 @@ "message": "Politika e privatësisë", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Documentation", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "mënyra e filtrimit", "description": "Label in the popup panel for the current filtering mode" @@ -87,14 +91,34 @@ "message": "Sipas rajonit, gjuhës", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Listat e importuar", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Shto një list filtrash…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL e listave të filtrave për të shtuar", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Importoj / Eksportoj", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Filtrat specifikë të personalizuar kalohen këtu", + "message": "Filtrat specifikë kozmetikë/skriptet shtohen këtu", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Hapni faqen e zgjerimeve të shfletuesit tuaj (chrome://extensions në Chrome ose about:addons në Firefox), hapni detajet e uBO Lite dhe aktivizoni Lejo skriptet e përdoruesit (të referuara edhe si \"skripte të palëve të treta të paverifikuara\").", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Ditari i ndryshimeve", "description": "" @@ -255,6 +279,22 @@ "message": "Uebsajtet potencialisht të padëshirueshme do të bllokohen dhe do t'ju jepet mundësia për të vazhduar.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Aktivizoj bllokimin e dritareve modale", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Kur aktivizohet, skedat e padëshirueshme që krijojnë uebsajtet do të mbyllen automatikisht nëse korrespondojnë me filtrat.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Ambienti i izoluar për krijimin e filtrave", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Këndi i zhvilluesit", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/sr/messages.json b/platform/mv3/extension/_locales/sr/messages.json index 3948ee4d86a59..88c997e31061c 100644 --- a/platform/mv3/extension/_locales/sr/messages.json +++ b/platform/mv3/extension/_locales/sr/messages.json @@ -4,7 +4,7 @@ "description": "extension name." }, "extShortDesc": { - "message": "Ефикасан блокатор садржаја. Блокира рекламе, праћења, рударе криптовалута, и много више одмах по инсталацији.", + "message": "Ефикасан блокатор садржаја. Блокира рекламе, праћења, рударе криптовалута и још много тога одмах након инсталације.", "description": "this will be in the Chrome web store: must be 132 characters or less" }, "perRulesetStats": { @@ -24,27 +24,31 @@ "description": "appears as tab name in dashboard" }, "developPageName": { - "message": "Развијте", + "message": "Програмирање", "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { - "message": "О апликацији", + "message": "О програму", "description": "appears as tab name in dashboard" }, "aboutPrivacyPolicy": { "message": "Политика приватности", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Документација", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "режим филтрирања", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "На овој веб страници", + "message": "На овом веб сајту", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "Пријавите проблем на овом веб сајту", + "message": "Пријави проблем", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Злонамерни домени", + "message": "Заштита од злонамерног софтвера, безбедност", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,14 +91,34 @@ "message": "Регионални, језички", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Увезене листе", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Додај листу филтера…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL листе филтера коју желите додати", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "За примену козметичких или скриптлет филтера из увезених листа, морате дати дозволу програму uBO Lite за покретање корисничких скрипти.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Увоз / извоз", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Овде налепите одређене козметичке филтере које желите додати", + "message": "Одређени козметички/скриптлет филтери које желите додати", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Отворите страницу проширења (chrome://extensions у Chrome или about:addons у Firefox прегледачу), отворите детаље о uBO Lite и укључите Дозволи корисничке скрипте (такође познате као „неверификоване скрипте трећих страна”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Списак измена", "description": "" @@ -136,11 +160,11 @@ "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "Да не бисте оптерећивали волонтере дуплим извештајима, проверите да ли је проблем већ пријављен.", + "message": "Да бисте избегли оптерећење волонтера дуплим извештајима, проверите да ли је проблем већ пријављен. Напомена: кликом на дугме, порекло странице ће бити послато GitHub-у.", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Пронађи сличне извештаје", + "message": "Пронађи сличне извештаје на GitHub-у", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { @@ -188,7 +212,7 @@ "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Креирај нови извештај", + "message": "Креирај нови извештај на GitHub-у", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { @@ -196,7 +220,7 @@ "description": "The header text for the default filtering mode section" }, "defaultFilteringModeDescription": { - "message": "Подразумевани режим филтрирања ће бити замењен режимима филтрирања по појединачним веб сајтовима. Можете прилагодити режим филтрирања на било ком веб сајту у складу са режимом који најбоље функционише на том веб сајту. Сваки режим има своје предности и мане.", + "message": "Подразумевани режим филтрирања ће бити замењен режимима филтрирања по појединачном веб сајту. Можете прилагодити режим филтрирања на било ком веб сајту у складу са режимом који најбоље функционише на том веб сајту. Сваки режим има своје предности и мане.", "description": "This describes the default filtering mode setting" }, "filteringMode0Name": { @@ -244,7 +268,7 @@ "description": "Label for a checkbox in the options page" }, "showBlockedCountLabel": { - "message": "Прикажи број блокираних захтева на иконици на траци алата", + "message": "Прикажи број блокираних захтева на иконици на алатној траци", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { @@ -255,8 +279,24 @@ "message": "Навигација до потенцијално непожељних сајтова ће бити блокирана и биће вам понуђена опција да наставите.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Омогући блокирање искачућих прозора", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Када је активно, одговарајући филтери ће аутоматски затворити нежељене картице прегледача које су креирале веб странице.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Изоловано окружење за креирање филтера", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "За примену козметичких или скриптлет филтера из изолованог окружења, морате дати дозволу програм uBO Lite за покретање корисничких скрипти.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Режим за програмере", + "message": "Режим програмерa", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { @@ -264,15 +304,15 @@ "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Направи резервну копију", + "message": "Резервна копија", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Napravite sigurnosnu kopiju prilagođenih postavki u datoteku ili ih vratite iz datoteke.", + "message": "Направите резервну копију прилагођених подешавања у датотеку или вратите прилагођена подешавања из датотеке.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Vraćanje će prepisati sve vaše trenutne prilagođene postavke.", + "message": "Враћање ће прегазити сва ваша тренутна прилагођена подешавања.", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { @@ -292,7 +332,7 @@ "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "Блокирана страница жели да преусмери на други сајт. Ако одлучите да наставите, бићете директно на: {{url}}", + "message": "Блокирана страница жели да преусмери на други сајт. Ако одлучите да наставите, бићете директно преусмерени на: {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { @@ -316,23 +356,23 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Уклоните елемент", + "message": "Уклони елемент", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Изађи из режима за затварање елемената", + "message": "Изађи из режима уклањања елемената", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Направите прилагођени филтер", + "message": "Креирај прилагођени филтер", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Уклоните прилагођени филтер", + "message": "Уклони прилагођени филтер", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { - "message": "Приказ:", + "message": "Прикажи:", "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { @@ -340,11 +380,11 @@ "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Прилагођена правила за DNR", + "message": "Прилагођена правила DNR-а", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "ДНР правила …", + "message": "DNR правила …", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { @@ -372,27 +412,27 @@ "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Извоз…", + "message": "Извези…", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Направите резервну копију…", + "message": "Направи резервну копију…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Вратите резервну копију…", + "message": "Врати…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "Врати на подразумевана подешавања…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "Сва ваша прилагођена подешавања ће бити уклоњена. Да ли заиста желите да вратите на подразумевана подешавања?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Не додајте садржај из непоузданих извора", + "message": "Немојте додавати садржај из непоузданих извора", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { @@ -404,7 +444,7 @@ "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Изаберите", + "message": "Изабери", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { diff --git a/platform/mv3/extension/_locales/sv/messages.json b/platform/mv3/extension/_locales/sv/messages.json index 56e7d92265842..e9bb43ec4f6b0 100644 --- a/platform/mv3/extension/_locales/sv/messages.json +++ b/platform/mv3/extension/_locales/sv/messages.json @@ -35,6 +35,10 @@ "message": "Integritetspolicy", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Dokumentation", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "filtreringsläge", "description": "Label in the popup panel for the current filtering mode" @@ -87,14 +91,34 @@ "message": "Regioner, språk", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Importerade listor", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Lägg till filterlista…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Filterlistans webbadress som ska läggas till", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "För att tillämpa kosmetiska filter eller skriptfilter från importerade listor måste du ge uBO Lite behörighet att köra användarskript.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Importera / Exportera", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Här klistrar du in specifika kosmetiska filter att lägga till", + "message": "Specifika kosmetiska/scriptlet-filter att lägga till", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Öppna webbläsarens tilläggssida (chrome://extensions i Chrome eller about:addons i Firefox), öppna uBO Lite detaljer och aktivera Tillåt användarskript (även kallade \"obekräftade tredjepartsskript\").", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Ändringslogg", "description": "" @@ -255,6 +279,22 @@ "message": "Navigering till potentiellt oönskade webbplatser kommer att blockeras och du kommer att erbjudas alternativet att fortsätta.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Aktivera popup-blockering", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "När funktionen är aktiv stänger matchande filter automatiskt oönskade flikar som webbplatser öppnat.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Sandlåda för filterskapande", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "För att tillämpa kosmetiska filter eller skriptfilter från sandlådan måste du ge uBO Lite behörighet att köra användarskript.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Utvecklarläge", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/sw/messages.json b/platform/mv3/extension/_locales/sw/messages.json index 881b780e38fa2..86058c8be7054 100644 --- a/platform/mv3/extension/_locales/sw/messages.json +++ b/platform/mv3/extension/_locales/sw/messages.json @@ -4,419 +4,459 @@ "description": "extension name." }, "extShortDesc": { - "message": "An efficient content blocker. Blocks ads, trackers, miners, and more immediately upon installation.", + "message": "Kizuizi cha maudhui chenye ufanisi. Huzuia matangazo, vifuatiliaji, wachimba madini, na mengine mara baada ya usakinishaji.", "description": "this will be in the Chrome web store: must be 132 characters or less" }, "perRulesetStats": { - "message": "{{ruleCount}} rules, converted from {{filterCount}} network filters", + "message": "{{ruleCount}} sheria, zilizobadilishwa kutoka vichujio {{filterCount}} vya mtandao", "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "dashboardName": { - "message": "uBO Lite — Dashboard", + "message": "uBO Lite — Dashibodi", "description": "English: uBO Lite — Dashboard" }, "settingsPageName": { - "message": "Settings", + "message": "Mipangilio", "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "Custom filters", + "message": "Vichujio maalum", "description": "appears as tab name in dashboard" }, "developPageName": { - "message": "Develop", + "message": "Tengeneza", "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { - "message": "About", + "message": "Kuhusu", "description": "appears as tab name in dashboard" }, "aboutPrivacyPolicy": { - "message": "Privacy policy", + "message": "Sera ya faragha", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Nyaraka", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { - "message": "filtering mode", + "message": "hali ya uchujaji", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "On this website", + "message": "Kwenye tovuti hii", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "Report an issue", + "message": "Ripoti tatizo", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { - "message": "Open the dashboard", + "message": "Fungua dashibodi", "description": "English: Click to open the dashboard" }, "popupMoreButton": { - "message": "More", + "message": "Zaidi", "description": "Label to be used to show popup panel sections" }, "popupLessButton": { - "message": "Less", + "message": "Pungua", "description": "Label to be used to hide popup panel sections" }, "3pGroupDefault": { - "message": "Default", + "message": "Chaguo-msingi", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAds": { - "message": "Ads", + "message": "Matangazo", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupPrivacy": { - "message": "Privacy", + "message": "Faragha", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Malware protection, security", + "message": "Ulinzi wa programu hasidi, usalama", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { - "message": "Annoyances", + "message": "Vikwazo", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMisc": { - "message": "Miscellaneous", + "message": "Mengineyo", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupRegions": { - "message": "Regions, languages", + "message": "Kanda, lugha", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "3pGroupImported": { + "message": "Orodha zilizoingizwa", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "customListImportLabel": { + "message": "Ongeza orodha ya vichujio…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL ya orodha ya vichujio ya kuongeza", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { - "message": "Import / Export", + "message": "Ingiza / Hamisha", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "Vichujio mahususi vya urembo/scriptlet vya kuongeza", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Fungua ukurasa wa viendelezi vya kivinjari chako (chrome://extensions kwenye Chrome au about:addons kwenye Firefox), fungua maelezo ya uBO Lite, na washa Ruhusu hati za mtumiaji (pia hujulikana kama \"hati zisizoidhinishwa za watu wengine\").", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { - "message": "Changelog", + "message": "Rekodi ya mabadiliko", "description": "" }, "aboutCode": { - "message": "Source code (GPLv3)", + "message": "Msimbo wa chanzo (GPLv3)", "description": "English: Source code (GPLv3)" }, "aboutContributors": { - "message": "Contributors", + "message": "Wachangiaji", "description": "English: Contributors" }, "aboutSourceCode": { - "message": "Source code", + "message": "Msimbo wa chanzo", "description": "Link text to source code repo" }, "aboutTranslations": { - "message": "Translations", + "message": "Tafsiri", "description": "Link text to translations repo" }, "aboutFilterLists": { - "message": "Filter lists", + "message": "Orodha za vichujio", "description": "Link text to uBO's own filter lists repo" }, "aboutDependencies": { - "message": "External dependencies (GPLv3-compatible):", + "message": "Utegemezi wa nje (unaooana na GPLv3):", "description": "Shown in the About pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "Ripoti tatizo la kichujio", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "Ripoti matatizo ya vichujio na tovuti maalum kwenye uBlockOrigin/uAssets wakaguzi wa masuala. Inahitaji akaunti ya GitHub.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting information", + "message": "Taarifa za utatuzi wa matatizo", "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "Ili kuepuka kuwawekea mzigo wajitolea kwa ripoti zinazorudiwa, tafadhali thibitisha kwamba tatizo halijaripotiwa tayari. Kumbuka: kubonyeza kitufe kutasababisha asili ya ukurasa kutumwa kwa GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "Tafuta ripoti zinazofanana kwenye GitHub", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "Anwani ya ukurasa wa wavuti:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "Ukurasa wa wavuti…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- Chagua ingizo --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "Inaonyesha matangazo au mabaki ya matangazo", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "Ina viwekeleo au usumbufu mwingine", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBO Lite", + "message": "Inagundua uBO Lite", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "Ina masuala yanayohusiana na faragha", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBO Lite is enabled", + "message": "Inakosea kufanya kazi wakati uBO Lite imewashwa", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "Inafungua vipeperushi au madirisha yasiyotakikana", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "Inaelekeza kwenye programu hasidi, ulaghai", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "Weka lebo ukurasa wa wavuti kama “NSFW” (“Si salama kwa kazi”)", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "Unda ripoti mpya kwenye GitHub", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { - "message": "Default filtering mode", + "message": "Hali ya uchujaji chaguo-msingi", "description": "The header text for the default filtering mode section" }, "defaultFilteringModeDescription": { - "message": "The default filtering mode will be overridden by per-website filtering modes. You can adjust the filtering mode on any given website according to whichever mode works best on that website. Each mode has its advantages and disadvantages.", + "message": "Hali ya uchujaji chaguo-msingi itabatilishwa na hali za uchujaji za kila tovuti. Unaweza kurekebisha hali ya uchujaji kwenye tovuti yoyote kulingana na hali inayofanya kazi vizuri zaidi kwenye tovuti hiyo. Kila hali ina faida na hasara zake.", "description": "This describes the default filtering mode setting" }, "filteringMode0Name": { - "message": "no filtering", + "message": "hakuna uchujaji", "description": "Name of blocking mode 0" }, "filteringMode1Name": { - "message": "basic", + "message": "msingi", "description": "Name of blocking mode 1" }, "filteringMode2Name": { - "message": "optimal", + "message": "bora", "description": "Name of blocking mode 2" }, "filteringMode3Name": { - "message": "complete", + "message": "kamili", "description": "Name of blocking mode 3" }, "basicFilteringModeDescription": { - "message": "Basic network filtering from selected filter lists.\n\nDoes not require permission to read and modify data on websites.", + "message": "Uchujaji wa mtandao wa msingi kutoka kwenye orodha za vichujio zilizochaguliwa.\n\nHaihitaji ruhusa ya kusoma na kurekebisha data kwenye tovuti.", "description": "This describes the 'basic' filtering mode" }, "optimalFilteringModeDescription": { - "message": "Advanced network filtering plus specific extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.", + "message": "Uchujaji wa mtandao wa hali ya juu pamoja na uchujaji uliopanuliwa maalum kutoka kwenye orodha za vichujio zilizochaguliwa.\n\nInahitaji ruhusa pana ya kusoma na kurekebisha data kwenye tovuti zote.", "description": "This describes the 'optimal' filtering mode" }, "completeFilteringModeDescription": { - "message": "Advanced network filtering plus specific and generic extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.\n\nGeneric extended filtering may cause higher web page resources usage.", + "message": "Uchujaji wa mtandao wa hali ya juu pamoja na uchujaji uliopanuliwa maalum na wa jumla kutoka kwenye orodha za vichujio zilizochaguliwa.\n\nInahitaji ruhusa pana ya kusoma na kurekebisha data kwenye tovuti zote.\n\nUchujaji uliopanuliwa wa jumla unaweza kusababisha matumizi makubwa ya rasilimali za ukurasa wa wavuti.", "description": "This describes the 'complete' filtering mode" }, "noFilteringModeDescription": { - "message": "List of websites for which no filtering will take place.", + "message": "Orodha ya tovuti ambazo hakuna uchujaji utafanyika.", "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { - "message": "[hostnames only]\nexample.com\ngames.example\n...", + "message": "[majina ya seva pekee]\nexample.com\ngames.example\n...", "description": "Default text for in edit field" }, "behaviorSectionLabel": { - "message": "Behavior", + "message": "Tabia", "description": "The header text for the 'Behavior' section" }, "autoReloadLabel": { - "message": "Automatically reload page when changing filtering mode", + "message": "Pakia upya ukurasa kiotomatiki wakati wa kubadilisha hali ya uchujaji", "description": "Label for a checkbox in the options page" }, "showBlockedCountLabel": { - "message": "Show the number of blocked requests on the toolbar icon", + "message": "Onyesha idadi ya maombi yaliyozuiwa kwenye aikoni ya upau wa vidhibiti", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "Enable strict blocking", + "message": "Washa uzuiaji mkali", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "Urambazaji kwenye tovuti zinazoweza kuwa zisizohitajika utazuiwa, na utapewa chaguo la kuendelea.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Washa uzuiaji wa pop-up", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Inapowashwa, vichujio vinavyolingana vitafunga kiotomatiki vipeperushi vya kivinjari visivyohitajika vilivyoundwa na tovuti.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Sanduku la mchanga la kuunda vichujio", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Developer mode", + "message": "Hali ya msanidi programu", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "Huwezesha ufikiaji wa vipengele vinavyofaa watumiaji wa kiufundi.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "Hifadhi nakala", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "Hifadhi nakala ya mipangilio yako maalum kwenye faili, au rejesha mipangilio yako maalum kutoka kwa faili.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "Kurejesha kutaandika juu ya mipangilio yako yote ya sasa maalum.", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "Find lists", + "message": "Tafuta orodha", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { - "message": "Page blocked", + "message": "Ukurasa umezuiwa", "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite has prevented the following page from loading:", + "message": "uBO Lite imezuia ukurasa ufuatao kupakia:", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "The page was blocked because of a matching filter in {{listname}}.", + "message": "Ukurasa ulizuiwa kwa sababu ya kichujio kinacholingana katika {{listname}}.", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "Ukurasa uliozuiwa unataka kuelekeza kwenye tovuti nyingine. Ukichagua kuendelea, utaelekezwa moja kwa moja kwenye: {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { - "message": "without parameters", + "message": "bila vigezo", "description": "Label to be used for the parameter-less URL" }, "strictblockBack": { - "message": "Go back", + "message": "Rudi nyuma", "description": "A button to go back to the previous web page" }, "strictblockClose": { - "message": "Close this window", + "message": "Funga dirisha hili", "description": "A button to close the current tab" }, "strictblockDontWarn": { - "message": "Don't warn me again about this site", + "message": "Usinionye tena kuhusu tovuti hii", "description": "Label for checkbox in document-blocked page" }, "strictblockProceed": { - "message": "Proceed", + "message": "Endelea", "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Remove an element", + "message": "Ondoa kipengele", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Exit element zapper mode", + "message": "Toka hali ya kuzima kipengele", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "Unda kichujio maalum", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "Ondoa kichujio maalum", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { - "message": "View:", + "message": "Tazama:", "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "Maelezo ya hali ya uchujaji", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "Sheria maalum za DNR", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "Sheria za DNR za …", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "Seti ya sheria inayobadilika", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "Seti ya sheria ya kipindi", "description": "An option in a dropdown list" }, "saveButton": { - "message": "Save", + "message": "Hifadhi", "description": "Text for buttons used to save changes" }, "revertButton": { - "message": "Revert", + "message": "Rejesha", "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "Add", + "message": "Ongeza", "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Import and append…", + "message": "Ingiza na ongeza…", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Export…", + "message": "Hamisha…", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "Hifadhi nakala…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "Rejesha…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "Weka upya kwa mipangilio chaguo-msingi…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "Mipangilio yako yote maalum itaondolewa. Je, kweli unataka kuweka upya kwa mipangilio chaguo-msingi?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "Usiongeze maudhui kutoka vyanzo visivyoaminika", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "Idadi ya sheria zilizosajiliwa: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "Sogeza kitelezi ili kuchagua inayolingana zaidi", "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Pick", + "message": "Chagua", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "Hakikisha", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "Unda", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "Chagua kichujio hapa chini ili kuangazia vipengele vinavyolingana kwenye ukurasa wa wavuti. Bonyeza pipa la taka ili kuondoa kichujio.", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/ta/messages.json b/platform/mv3/extension/_locales/ta/messages.json index 2ff4d939a263c..2f3469db9f8fe 100644 --- a/platform/mv3/extension/_locales/ta/messages.json +++ b/platform/mv3/extension/_locales/ta/messages.json @@ -8,11 +8,11 @@ "description": "this will be in the Chrome web store: must be 132 characters or less" }, "perRulesetStats": { - "message": "{{ruleCount}} rules, converted from {{filterCount}} network filters", + "message": "{{ruleCount}} விதிகள், {{filterCount}} பிணைய வடிப்பான்களிலிருந்து மாற்றப்பட்டது", "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "dashboardName": { - "message": "uBO Lite — Dashboard", + "message": "uBO Lite — டாஷ்போர்டு", "description": "English: uBO Lite — Dashboard" }, "settingsPageName": { @@ -24,7 +24,7 @@ "description": "appears as tab name in dashboard" }, "developPageName": { - "message": "Develop", + "message": "உருவாக்கு", "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { @@ -35,20 +35,24 @@ "message": "தனியுரிமை கொள்கை", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "ஆவணமாக்கல்", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { - "message": "filtering mode", + "message": "வடிகட்டல் முறை", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "On this website", + "message": "இந்த இணையதளத்தில்", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "Report an issue", + "message": "சிக்கலைப் புகாரளிக்கவும்", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { - "message": "Open the dashboard", + "message": "டாஷ்போர்டைத் திறக்கவும்", "description": "English: Click to open the dashboard" }, "popupMoreButton": { @@ -56,11 +60,11 @@ "description": "Label to be used to show popup panel sections" }, "popupLessButton": { - "message": "Less", + "message": "குறைவு", "description": "Label to be used to hide popup panel sections" }, "3pGroupDefault": { - "message": "Default", + "message": "இயல்புநிலை", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAds": { @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Malware protection, security", + "message": "தீம்பொருள் பாதுகாப்பு, பாதுகாப்பு", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -84,23 +88,43 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupRegions": { - "message": "Regions, languages", + "message": "பகுதிகள், மொழிகள்", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "3pGroupImported": { + "message": "இறக்குமதி செய்யப்பட்ட பட்டியல்கள்", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "customListImportLabel": { + "message": "வடிப்பான் பட்டியலைச் சேர்க்கவும்…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "சேர்க்க வேண்டிய வடிப்பான் பட்டியலின் URL", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "இறக்குமதி / ஏற்றுமதி", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "சேர்க்க வேண்டிய குறிப்பிட்ட அழகியல்/ஸ்கிரிப்ட்லெட் வடிப்பான்கள்", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "உங்கள் உலாவியின் நீட்டிப்புகள் பக்கத்தைத் திறக்கவும் (Chrome இல் chrome://extensions அல்லது Firefox இல் about:addons), uBO Lite விவரங்களைத் திறக்கவும், மேலும் பயனர் ஸ்கிரிப்ட்களை அனுமதி (இது “சரிபார்க்கப்படாத மூன்றாம் தரப்பு ஸ்கிரிப்ட்கள்” என்றும் குறிப்பிடப்படுகிறது) என்பதை இயக்கவும்.", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "மாற்றப்பதிவேடு", "description": "" }, "aboutCode": { - "message": "Source code (GPLv3)", + "message": "மூலக் குறியீடு (GPLv3)", "description": "English: Source code (GPLv3)" }, "aboutContributors": { @@ -124,11 +148,11 @@ "description": "Shown in the About pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "வடிப்பான் சிக்கலைப் புகாரளிக்கவும்", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "குறிப்பிட்ட இணையதளங்களில் உள்ள வடிப்பான் சிக்கல்களை uBlockOrigin/uAssets சிக்கல் கண்காணிப்பாளரிடம் புகாரளிக்கவும். GitHub கணக்கு தேவை.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { @@ -136,11 +160,11 @@ "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "தன்னார்வலர்களுக்கு நகல் அறிக்கைகளால் சுமையை ஏற்படுத்துவதைத் தவிர்க்க, இந்த சிக்கல் ஏற்கனவே புகாரளிக்கப்படவில்லை என்பதை உறுதிசெய்யவும். குறிப்பு: பொத்தானைக் கிளிக் செய்வதால் பக்கத்தின் மூல (origin) GitHub க்கு அனுப்பப்படும்.", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "GitHub இல் ஒத்த அறிக்கைகளைக் கண்டறியவும்", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { @@ -152,7 +176,7 @@ "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- ஒரு உள்ளீட்டைத் தேர்வு செய்யவும் --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { @@ -164,39 +188,39 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBO Lite", + "message": "uBO Lite ஐ கண்டறிகிறது", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "தனியுரிமை தொடர்பான சிக்கல்கள் உள்ளன", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBO Lite is enabled", + "message": "uBO Lite இயக்கப்பட்டிருக்கும் போது செயலிழக்கிறது", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "தேவையற்ற தாவல்கள் அல்லது சாளரங்களைத் திறக்கிறது", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "தீம்பொருள், பிஷிங் போன்றவற்றிற்கு இட்டுச்செல்கிறது", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "இணையப் பக்கத்தை “NSFW” (“பணிக்கு பாதுகாப்பானது அல்ல”) என்று பெயரிடவும்", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "GitHub இல் புதிய அறிக்கையை உருவாக்கவும்", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { - "message": "Default filtering mode", + "message": "இயல்புநிலை வடிகட்டல் முறை", "description": "The header text for the default filtering mode section" }, "defaultFilteringModeDescription": { - "message": "The default filtering mode will be overridden by per-website filtering modes. You can adjust the filtering mode on any given website according to whichever mode works best on that website. Each mode has its advantages and disadvantages.", + "message": "இயல்புநிலை வடிகட்டல் முறையானது, ஒவ்வொரு இணையதளத்திற்குமான வடிகட்டல் முறைகளால் மேலெழுதப்படும். எந்த முறை அந்த இணையதளத்தில் சிறப்பாகச் செயல்படுகிறதோ அதன் அடிப்படையில், எந்தவொரு இணையதளத்திலும் நீங்கள் வடிகட்டல் முறையை சரிசெய்யலாம். ஒவ்வொரு முறைக்கும் அதன் நன்மைகள் மற்றும் தீமைகள் உள்ளன.", "description": "This describes the default filtering mode setting" }, "filteringMode0Name": { @@ -216,207 +240,223 @@ "description": "Name of blocking mode 3" }, "basicFilteringModeDescription": { - "message": "Basic network filtering from selected filter lists.\n\nDoes not require permission to read and modify data on websites.", + "message": "தேர்ந்தெடுக்கப்பட்ட வடிப்பான் பட்டியல்களில் இருந்து அடிப்படை பிணைய வடிகட்டல்.\n\nஇணையதளங்களில் தரவைப் படிக்கவும் மாற்றியமைக்கவும் அனுமதி தேவையில்லை.", "description": "This describes the 'basic' filtering mode" }, "optimalFilteringModeDescription": { - "message": "Advanced network filtering plus specific extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.", + "message": "மேம்பட்ட பிணைய வடிகட்டல் மற்றும் தேர்ந்தெடுக்கப்பட்ட வடிப்பான் பட்டியல்களில் இருந்து குறிப்பிட்ட நீட்டிக்கப்பட்ட வடிகட்டல்.\n\nஅனைத்து இணையதளங்களிலும் தரவைப் படிக்கவும் மாற்றியமைக்கவும் விரிவான அனுமதி தேவை.", "description": "This describes the 'optimal' filtering mode" }, "completeFilteringModeDescription": { - "message": "Advanced network filtering plus specific and generic extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.\n\nGeneric extended filtering may cause higher web page resources usage.", + "message": "மேம்பட்ட பிணைய வடிகட்டல் மற்றும் தேர்ந்தெடுக்கப்பட்ட வடிப்பான் பட்டியல்களில் இருந்து குறிப்பிட்ட மற்றும் பொதுவான நீட்டிக்கப்பட்ட வடிகட்டல்.\n\nஅனைத்து இணையதளங்களிலும் தரவைப் படிக்கவும் மாற்றியமைக்கவும் விரிவான அனுமதி தேவை.\n\nபொதுவான நீட்டிக்கப்பட்ட வடிகட்டல் இணையப் பக்க வளப் பயன்பாட்டை அதிகரிக்கலாம்.", "description": "This describes the 'complete' filtering mode" }, "noFilteringModeDescription": { - "message": "List of websites for which no filtering will take place.", + "message": "எந்த வடிகட்டலும் நடைபெறாத இணையதளங்களின் பட்டியல்.", "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { - "message": "[hostnames only]\nexample.com\ngames.example\n...", + "message": "[ஹோஸ்ட்பெயர்கள் மட்டும்]\nexample.com\ngames.example\n...", "description": "Default text for in edit field" }, "behaviorSectionLabel": { - "message": "Behavior", + "message": "நடத்தை", "description": "The header text for the 'Behavior' section" }, "autoReloadLabel": { - "message": "Automatically reload page when changing filtering mode", + "message": "வடிகட்டல் முறையை மாற்றும்போது பக்கத்தை தானாக மீண்டும் ஏற்றவும்", "description": "Label for a checkbox in the options page" }, "showBlockedCountLabel": { - "message": "Show the number of blocked requests on the toolbar icon", + "message": "கருவிப்பட்டியல் ஐகானில் தடுக்கப்பட்ட கோரிக்கைகளின் எண்ணிக்கையைக் காட்டு", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "Enable strict blocking", + "message": "கடுமையான தடுப்பை இயக்கு", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "சாத்தியமான தேவையற்ற தளங்களுக்கான வழிச்செலுத்தல் தடுக்கப்படும், மேலும் தொடர்ந்து செல்லும் விருப்பம் உங்களுக்கு வழங்கப்படும்.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "பாப்-அப் தடுப்பை இயக்கு", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "செயலில் இருக்கும்போது, பொருந்தும் வடிப்பான்கள், இணையதளங்களால் உருவாக்கப்பட்ட தேவையற்ற உலாவி தாவல்களை தானாகவே மூடும்.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "வடிப்பான் உருவாக்கும் மணல் பெட்டி (sandbox)", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Developer mode", + "message": "டெவலப்பர் முறை", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "தொழில்நுட்ப பயனர்களுக்கு ஏற்ற அம்சங்களுக்கான அணுகலை இயக்குகிறது.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "காப்பு", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "உங்கள் தனிப்பயன் அமைப்புகளை ஒரு கோப்பில் காப்புப் பிரதி எடுக்கவும், அல்லது ஒரு கோப்பில் இருந்து உங்கள் தனிப்பயன் அமைப்புகளை மீட்டெடுக்கவும்.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "மீட்டமைப்பது உங்கள் தற்போதைய அனைத்து தனிப்பயன் அமைப்புகளையும் மேலெழுதும்.", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "Find lists", + "message": "பட்டியல்களைக் கண்டறியவும்", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { - "message": "Page blocked", + "message": "பக்கம் தடுக்கப்பட்டது", "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite has prevented the following page from loading:", + "message": "uBO Lite பின்வரும் பக்கம் ஏற்றப்படுவதைத் தடுத்துள்ளது:", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "The page was blocked because of a matching filter in {{listname}}.", + "message": "{{listname}} இல் பொருந்திய வடிப்பான் காரணமாக பக்கம் தடுக்கப்பட்டது.", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "தடுக்கப்பட்ட பக்கம் வேறொரு தளத்திற்கு திருப்பிவிட முயல்கிறது. நீங்கள் தொடர்ந்து செல்ல தேர்வுசெய்தால், நீங்கள் நேரடியாக இங்கு செல்லுவீர்கள்: {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { - "message": "without parameters", + "message": "அளவுருக்கள் இல்லாமல்", "description": "Label to be used for the parameter-less URL" }, "strictblockBack": { - "message": "Go back", + "message": "திரும்பிச் செல்", "description": "A button to go back to the previous web page" }, "strictblockClose": { - "message": "Close this window", + "message": "இந்த சாளரத்தை மூடு", "description": "A button to close the current tab" }, "strictblockDontWarn": { - "message": "Don't warn me again about this site", + "message": "இந்த தளத்தைப் பற்றி மீண்டும் என்னை எச்சரிக்க வேண்டாம்", "description": "Label for checkbox in document-blocked page" }, "strictblockProceed": { - "message": "Proceed", + "message": "தொடரவும்", "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Remove an element", + "message": "ஒரு உறுப்பை அகற்று", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Exit element zapper mode", + "message": "உறுப்பு ஜாப்பர் முறையிலிருந்து வெளியேறு", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "தனிப்பயன் வடிப்பானை உருவாக்கு", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "தனிப்பயன் வடிப்பானை அகற்று", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { - "message": "View:", + "message": "காட்சி:", "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "வடிகட்டல் முறை விவரங்கள்", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "தனிப்பயன் DNR விதிகள்", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "… இன் DNR விதிகள்", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "மாறும் விதித் தொகுப்பு", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "அமர்வு விதித் தொகுப்பு", "description": "An option in a dropdown list" }, "saveButton": { - "message": "Save", + "message": "சேமி", "description": "Text for buttons used to save changes" }, "revertButton": { - "message": "Revert", + "message": "மீட்டமை", "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "Add", + "message": "சேர்", "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Import and append…", + "message": "இறக்குமதி செய்து இணை…", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Export…", + "message": "ஏற்றுமதி…", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "காப்புப் பிரதி எடு…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "மீட்டமை…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "இயல்புநிலை அமைப்புகளுக்கு மீட்டமை…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "உங்கள் அனைத்து தனிப்பயன் அமைப்புகளும் அகற்றப்படும். இயல்புநிலை அமைப்புகளுக்கு மீட்டமைக்க உண்மையில் விரும்புகிறீர்களா?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "நம்பத்தகாத மூலங்களிலிருந்து உள்ளடக்கத்தைச் சேர்க்க வேண்டாம்", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "பதிவுசெய்யப்பட்ட விதிகளின் எண்ணிக்கை: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "சிறந்த பொருத்தத்தைத் தேர்ந்தெடுக்க ஸ்லைடரை நகர்த்தவும்", "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Pick", + "message": "தேர்வு செய்", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "முன்னோட்டம்", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "உருவாக்கு", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "இணையப் பக்கத்தில் பொருந்தும் உறுப்புகளை முன்னிலைப்படுத்த கீழே உள்ள ஒரு வடிப்பானைத் தேர்ந்தெடுக்கவும். ஒரு வடிப்பானை அகற்ற குப்பைத் தொட்டியைக் கிளிக் செய்யவும்.", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/te/messages.json b/platform/mv3/extension/_locales/te/messages.json index 03e43f94efc15..39cce771fae87 100644 --- a/platform/mv3/extension/_locales/te/messages.json +++ b/platform/mv3/extension/_locales/te/messages.json @@ -4,15 +4,15 @@ "description": "extension name." }, "extShortDesc": { - "message": "An efficient content blocker. Blocks ads, trackers, miners, and more immediately upon installation.", + "message": "ఒక సమర్థవంతమైన కంటెంట్ బ్లాకర్. ప్రకటనలు, ట్రాకర్లు, మైనర్లు మరియు మరిన్నింటిని ఇన్‌స్టాల్ చేసిన వెంటనే బ్లాక్ చేస్తుంది.", "description": "this will be in the Chrome web store: must be 132 characters or less" }, "perRulesetStats": { - "message": "{{ruleCount}} rules, converted from {{filterCount}} network filters", + "message": "{{ruleCount}} నియమాలు, {{filterCount}} నెట్‌వర్క్ ఫిల్టర్ల నుండి మార్చబడ్డాయి", "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "dashboardName": { - "message": "uBO Lite — Dashboard", + "message": "uBO Lite — డాష్‌బోర్డ్", "description": "English: uBO Lite — Dashboard" }, "settingsPageName": { @@ -20,11 +20,11 @@ "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "Custom filters", + "message": "అనుకూల ఫిల్టర్లు", "description": "appears as tab name in dashboard" }, "developPageName": { - "message": "Develop", + "message": "అభివృద్ధి", "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { @@ -35,16 +35,20 @@ "message": "గోప్యతా", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "డాక్యుమెంటేషన్", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "వడపోత మోడ్", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "On this website", + "message": "ఈ వెబ్‌సైట్‌లో", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "Report an issue", + "message": "సమస్యను నివేదించండి", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { @@ -72,147 +76,167 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Malware protection, security", + "message": "మాల్వేర్ రక్షణ, భద్రత", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { - "message": "Annoyances", + "message": "బాధించేవి", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMisc": { - "message": "Miscellaneous", + "message": "ఇతరములు", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupRegions": { - "message": "Regions, languages", + "message": "ప్రాంతాలు, భాషలు", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "3pGroupImported": { + "message": "దిగుమతి చేసిన జాబితాలు", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "customListImportLabel": { + "message": "ఫిల్టర్ జాబితాను జోడించండి…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "జోడించవలసిన ఫిల్టర్ జాబితా యొక్క URL", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { - "message": "Import / Export", + "message": "దిగుమతి / ఎగుమతి", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "జోడించడానికి నిర్దిష్ట కాస్మెటిక్/స్క్రిప్ట్‌లెట్ ఫిల్టర్లు", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "మీ బ్రౌజర్ యొక్క ఎక్స్‌టెన్షన్ పేజీని తెరవండి (chrome://extensions Chromeలో లేదా about:addons Firefoxలో), uBO Lite వివరాలను తెరవండి, మరియు Allow user scripts (లేదా “unverified third-party scripts” అని కూడా పిలుస్తారు) టోగుల్ చేయండి.", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { - "message": "Changelog", + "message": "మార్పుల చరిత్ర", "description": "" }, "aboutCode": { - "message": "Source code (GPLv3)", + "message": "సోర్స్ కోడ్ (GPLv3)", "description": "English: Source code (GPLv3)" }, "aboutContributors": { - "message": "Contributors", + "message": "సహాయకులు", "description": "English: Contributors" }, "aboutSourceCode": { - "message": "Source code", + "message": "సోర్స్ కోడ్", "description": "Link text to source code repo" }, "aboutTranslations": { - "message": "Translations", + "message": "అనువాదాలు", "description": "Link text to translations repo" }, "aboutFilterLists": { - "message": "Filter lists", + "message": "ఫిల్టర్ జాబితాలు", "description": "Link text to uBO's own filter lists repo" }, "aboutDependencies": { - "message": "External dependencies (GPLv3-compatible):", + "message": "బాహ్య ఆధారాలు (GPLv3-అనుకూలమైనవి):", "description": "Shown in the About pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "ఫిల్టర్ సమస్యను నివేదించండి", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "నిర్దిష్ట వెబ్‌సైట్లతో ఫిల్టర్ సమస్యలను uBlockOrigin/uAssets ఇష్యూ ట్రాకర్‌కు నివేదించండి. GitHub ఖాతా అవసరం.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting information", + "message": "సమస్య పరిష్కార సమాచారం", "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "నకిలీ నివేదికలతో స్వచ్ఛంద సేవకులకు భారం కలగకుండా ఉండటానికి, సమస్య ఇప్పటికే నివేదించబడలేదని ధృవీకరించండి. గమనిక: బటన్‌ను క్లిక్ చేయడం వలన పేజీ యొక్క మూలం GitHubకు పంపబడుతుంది.", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "GitHubలో సారూప్య నివేదికలను కనుగొనండి", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "వెబ్ పేజీ చిరునామా:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "వెబ్ పేజీ…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- ఒక ఎంపికను ఎంచుకోండి --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "ప్రకటనలు లేదా ప్రకటన అవశేషాలను చూపిస్తుంది", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "ఓవర్లేలు లేదా ఇతర అసౌకర్యాలు ఉన్నాయి", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBO Lite", + "message": "uBO Liteను గుర్తిస్తుంది", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "గోప్యత-సంబంధిత సమస్యలు ఉన్నాయి", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBO Lite is enabled", + "message": "uBO Lite ప్రారంభించబడినప్పుడు పనిచేయకపోవడం", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "అవాంఛిత టాబ్‌లు లేదా విండోలను తెరుస్తుంది", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "చెడు సాఫ్ట్‌వేర్, ఫిషింగ్‌కు దారితీస్తుంది", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "వెబ్ పేజీని “NSFW” (“పనికి సురక్షితం కాదు”) గా లేబుల్ చేయండి", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "GitHubలో కొత్త నివేదికను సృష్టించండి", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { - "message": "Default filtering mode", + "message": "డిఫాల్ట్ ఫిల్టరింగ్ మోడ్", "description": "The header text for the default filtering mode section" }, "defaultFilteringModeDescription": { - "message": "The default filtering mode will be overridden by per-website filtering modes. You can adjust the filtering mode on any given website according to whichever mode works best on that website. Each mode has its advantages and disadvantages.", + "message": "డిఫాల్ట్ ఫిల్టరింగ్ మోడ్ ప్రతి-వెబ్‌సైట్ ఫిల్టరింగ్ మోడ్ల ద్వారా ఓవర్‌రైడ్ చేయబడుతుంది. మీరు ఏదైనా వెబ్‌సైట్‌లో ఆ వెబ్‌సైట్‌కు బాగా పనిచేసే మోడ్ ప్రకారం ఫిల్టరింగ్ మోడ్ను సర్దుబాటు చేయవచ్చు. ప్రతి మోడ్ దాని ప్రయోజనాలు మరియు అప్రయోజనాలను కలిగి ఉంటుంది.", "description": "This describes the default filtering mode setting" }, "filteringMode0Name": { - "message": "no filtering", + "message": "ఫిల్టరింగ్ లేదు", "description": "Name of blocking mode 0" }, "filteringMode1Name": { - "message": "basic", + "message": "ప్రాథమిక", "description": "Name of blocking mode 1" }, "filteringMode2Name": { - "message": "optimal", + "message": "అత్యుత్తమ", "description": "Name of blocking mode 2" }, "filteringMode3Name": { - "message": "complete", + "message": "పూర్తి", "description": "Name of blocking mode 3" }, "basicFilteringModeDescription": { @@ -232,7 +256,7 @@ "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { - "message": "[hostnames only]\nexample.com\ngames.example\n...", + "message": "[హోస్ట్‌నేమ్లు మాత్రమే]\nexample.com\ngames.example\n...", "description": "Default text for in edit field" }, "behaviorSectionLabel": { @@ -244,179 +268,195 @@ "description": "Label for a checkbox in the options page" }, "showBlockedCountLabel": { - "message": "Show the number of blocked requests on the toolbar icon", + "message": "టూల్బార్ చిహ్నంపై నిరోధించబడిన అభ్యర్థనల సంఖ్యను చూపించు", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "Enable strict blocking", + "message": "కఠినమైన బ్లాకింగ్‌ను ప్రారంభించండి", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "సంభావ్యంగా అవాంఛనీయ సైట్లకు నావిగేషన్ నిరోధించబడుతుంది మరియు మీరు కొనసాగడానికి ఎంపికను అందించబడతారు.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "పాప్-అప్ బ్లాకింగ్‌ను ప్రారంభించండి", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "క్రియాశీలంగా ఉన్నప్పుడు, సరిపోలే ఫిల్టర్లు వెబ్‌సైట్ల ద్వారా సృష్టించబడిన అవాంఛిత బ్రౌజర్ టాబ్‌లను స్వయంచాలకంగా మూసివేస్తాయి.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "ఫిల్టర్-సృష్టి శాండ్‌బాక్స్", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Developer mode", + "message": "డెవలపర్ మోడ్", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "సాంకేతిక వినియోగదారులకు అనువైన ఫీచర్లకు ప్రాప్యతను ప్రారంభిస్తుంది.", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "బ్యాకప్", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "మీ అనుకూల సెట్టింగ్‌లను ఫైల్‌కు బ్యాకప్ చేయండి, లేదా ఫైల్ నుండి మీ అనుకూల సెట్టింగ్‌లను పునరుద్ధరించండి.", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "పునరుద్ధరించడం మీ ప్రస్తుత అనుకూల సెట్టింగ్‌లన్నింటినీ ఓవర్‌రైట్ చేస్తుంది.", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "Find lists", + "message": "జాబితాలను కనుగొనండి", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { - "message": "Page blocked", + "message": "పేజీ నిరోధించబడింది", "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite has prevented the following page from loading:", + "message": "uBO Lite కింది పేజీని లోడ్ కాకుండా నిరోధించింది:", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "The page was blocked because of a matching filter in {{listname}}.", + "message": "{{listname}}లో సరిపోలే ఫిల్టర్ కారణంగా పేజీ నిరోధించబడింది.", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "నిరోధించబడిన పేజీ మరొక సైట్‌కు దారి మళ్ళించాలనుకుంటుంది. మీరు కొనసాగించాలని ఎంచుకుంటే, మీరు నేరుగా ఇక్కడికి నావిగేట్ చేస్తారు: {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { - "message": "without parameters", + "message": "పారామితులు లేకుండా", "description": "Label to be used for the parameter-less URL" }, "strictblockBack": { - "message": "Go back", + "message": "వెనుకకు వెళ్ళు", "description": "A button to go back to the previous web page" }, "strictblockClose": { - "message": "Close this window", + "message": "ఈ విండోను మూసివేయి", "description": "A button to close the current tab" }, "strictblockDontWarn": { - "message": "Don't warn me again about this site", + "message": "ఈ సైట్ గురించి మళ్ళీ నాకు హెచ్చరించవద్దు", "description": "Label for checkbox in document-blocked page" }, "strictblockProceed": { - "message": "Proceed", + "message": "కొనసాగించండి", "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Remove an element", + "message": "ఒక మూలకాన్ని తొలగించండి", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Exit element zapper mode", + "message": "ఎలిమెంట్ జాపర్ మోడ్ నుండి నిష్క్రమించండి", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "అనుకూల ఫిల్టర్‌ను సృష్టించండి", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "అనుకూల ఫిల్టర్‌ను తొలగించండి", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { - "message": "View:", + "message": "వీక్షించు:", "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "ఫిల్టరింగ్ మోడ్ వివరాలు", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "అనుకూల DNR నియమాలు", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "DNR నియమాలు …", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "డైనమిక్ రూల్‌సెట్", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "సెషన్ రూల్‌సెట్", "description": "An option in a dropdown list" }, "saveButton": { - "message": "Save", + "message": "సేవ్ చేయండి", "description": "Text for buttons used to save changes" }, "revertButton": { - "message": "Revert", + "message": "రివర్ట్ చేయండి", "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "Add", + "message": "జోడించు", "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Import and append…", + "message": "దిగుమతి చేసి జోడించు…", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Export…", + "message": "ఎగుమతి…", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "బ్యాకప్…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "పునరుద్ధరించు…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "డిఫాల్ట్ సెట్టింగ్‌లకు రీసెట్ చేయి…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "మీ అనుకూల సెట్టింగ్‌లన్నీ తొలగించబడతాయి. మీరు నిజంగా డిఫాల్ట్ సెట్టింగ్‌లకు రీసెట్ చేయాలనుకుంటున్నారా?", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "విశ్వసనీయం కాని మూలాల నుండి కంటెంట్‌ను జోడించవద్దు", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "నమోదు చేసిన నియమాల సంఖ్య: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "ఉత్తమ మ్యాచ్‌ను ఎంచుకోవడానికి స్లయిడర్‌ను తరలించండి", "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Pick", + "message": "ఎంచుకోండి", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "ప్రివ్యూ", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "సృష్టించు", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "వెబ్ పేజీలో సరిపోలే మూలకాలను హైలైట్ చేయడానికి క్రింద ఒక ఫిల్టర్‌ను ఎంచుకోండి. ఫిల్టర్‌ను తొలగించడానికి చెత్త డబ్బాపై క్లిక్ చేయండి.", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/th/messages.json b/platform/mv3/extension/_locales/th/messages.json index cd15ebc52962c..f1e107bf9d26c 100644 --- a/platform/mv3/extension/_locales/th/messages.json +++ b/platform/mv3/extension/_locales/th/messages.json @@ -35,6 +35,10 @@ "message": "นโยบายความเป็นส่วนตัว", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Documentation", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "โหมดตัวกรอง", "description": "Label in the popup panel for the current filtering mode" @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "การป้องกันมัลแวร์ ความปลอดภัย", + "message": "การป้องกันมัลแวร์, ความปลอดภัย", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,14 +91,34 @@ "message": "ภูมิภาค, ภาษา", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Imported lists", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Add filter list…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL of the filter list to add", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "นำเข้า / ส่งออก", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "Specific cosmetic/scriptlet filters to add", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Open your browser's extensions page (chrome://extensions in Chrome or about:addons in Firefox), open uBO Lite details, and toggle on Allow user scripts (also referred to as “unverified third-party scripts”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "บันทึการเปลี่ยนแปลง", "description": "" @@ -255,6 +279,22 @@ "message": "การนำทางไปยังเว็บไซต์ที่ไม่พึงประสงค์จะถูกบล็อก และคุณจะได้รับตัวเลือกเพื่อดำเนินการต่อ", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Enable pop-up blocking", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "When active, matching filters will automatically close unwanted browser tabs created by websites.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Filter-creation sandbox", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "โหมดนักพัฒนา", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/tr/messages.json b/platform/mv3/extension/_locales/tr/messages.json index f80e64bcab16d..af07e5a6b10e7 100644 --- a/platform/mv3/extension/_locales/tr/messages.json +++ b/platform/mv3/extension/_locales/tr/messages.json @@ -35,6 +35,10 @@ "message": "Gizlilik ilkesi", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Belgeler", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "Filtreleme modu", "description": "Label in the popup panel for the current filtering mode" @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Zararlı alan adları", + "message": "Kötü amaçlı yazılım koruması, güvenlik", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,6 +91,22 @@ "message": "Bölgeler, diller", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "İçeri aktarılan listeler", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Filtre listesi ekle…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Eklenecek filtre listesinin URL'sini buraya yapıştırın", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "İçe aktarılan listelerden kozmetik veya scriptlet filtrelerini uygulamak için, uBO Lite’a kullanıcı komut dosyalarını çalıştırma izni vermeniz gerekir.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "İçeri/Dışarı aktar", "description": "Text label heading the import/export area of custom filters" @@ -95,6 +115,10 @@ "message": "Eklenmesi için kozmetik filtreleri buraya yapıştırın", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Tarayıcınızın uzantılar sayfasını açın (Chrome için:chrome://extensions Firefox için:about:addons), uBO Lite'ın ayrıntılar sayfasına tıklayın ve Kullanıcı komut dosyalarına izin ver seçeneğine tıklayın (\"doğrulanmamış 3. parti komutlar\" olarak da adlandırılabilir).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Değişiklik günlüğü", "description": "" @@ -255,6 +279,22 @@ "message": "İstenmeyebilecek sitelere erişim engellenecek ve devam etme seçeneği sunulacaktır.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Açılır pencere engellemeyi etkinleştir", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Etkinleştirildiğinde, uygun filtreler web sitelerinin açtığı istenmeyen sekmeleri otomatik olarak kapatır.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Filtre oluşturma alanı", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "Sandbox'tan kozmetik veya scriptlet filtrelerini uygulamak için, uBO Lite'a kullanıcı komut dosyalarını çalıştırma izni vermeniz gerekir.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Geliştirici modu", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/uk/messages.json b/platform/mv3/extension/_locales/uk/messages.json index f1dcd40ea6e63..ed56d9250ed02 100644 --- a/platform/mv3/extension/_locales/uk/messages.json +++ b/platform/mv3/extension/_locales/uk/messages.json @@ -35,6 +35,10 @@ "message": "Політика конфіденційності", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Документація", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "режим фільтрації", "description": "Label in the popup panel for the current filtering mode" @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Домени шкідливих програм", + "message": "Захист від шкідливих програм, безпека", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,6 +91,22 @@ "message": "Регіони, мови", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Імпортовані списки", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Додати список фільтрів…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "Вставте сюди URL-адресу списку фільтрів, який потрібно додати", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "Щоб застосувати косметичні фільтри або фільтри на основі скриптів з імпортованих списків, необхідно надати uBO Lite дозвіл на виконання користувацьких скриптів.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Імпорт / Експорт", "description": "Text label heading the import/export area of custom filters" @@ -95,6 +115,10 @@ "message": "Вставте сюди конкретні косметичні фільтри, які потрібно додати", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Відкрийте сторінку розширень у браузері (chrome://extensions у Chrome або about:addons у Firefox), перейдіть до детальної інформації про uBO Lite та увімкніть опцію «Дозволити користувацькі скрипти» (також відомі як «неперевірені сторонні скрипти»).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Журнал змін", "description": "" @@ -255,6 +279,22 @@ "message": "Перехід до потенційно небажаних сайтів буде заблоковано, та вам буде запропоновано можливість продовжити", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Увімкнути блокування спливних вікон", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Якщо увімкнено, фільтри автоматично закриватимуть небажані вкладки браузера, створені вебсайтами.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Пісочниця створення фільтру", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "Щоб застосувати косметичні фільтри або фільтри на основі скриптів із пісочниці, необхідно надати uBO Lite дозвіл на виконання користувацьких скриптів.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Режим розробника", "description": "Label for a checkbox in the options page" @@ -316,7 +356,7 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Перейти в режим тимчасового приховування елементів", + "message": "Видалити елемент", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { diff --git a/platform/mv3/extension/_locales/ur/messages.json b/platform/mv3/extension/_locales/ur/messages.json index 9a78773d02dc3..d8918aa838bbf 100644 --- a/platform/mv3/extension/_locales/ur/messages.json +++ b/platform/mv3/extension/_locales/ur/messages.json @@ -20,11 +20,11 @@ "description": "appears as tab name in dashboard" }, "customFiltersPageName": { - "message": "Custom filters", + "message": "حسب ضرورت فلٹرز", "description": "appears as tab name in dashboard" }, "developPageName": { - "message": "Develop", + "message": "ڈیولپ", "description": "appears as tab name in dashboard. Inspired from 'Develop' menu in Safari, see https://developer.apple.com/documentation/safari-developer-tools/develop-menu" }, "aboutPageName": { @@ -35,16 +35,20 @@ "message": "پرائیویسی پالیسی", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "دستاویزات", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "فلٹرنگ موڈ", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "On this website", + "message": "اس ویب سائٹ پر", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "Report an issue", + "message": "مسئلہ رپورٹ کریں", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "Malware protection, security", + "message": "مالویئر تحفظ، سیکیورٹی", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,14 +91,34 @@ "message": "علاقے، زبانیں۔", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "درآمد شدہ فہرستیں", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "فلٹر لسٹ شامل کریں…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "شامل کرنے کے لیے فلٹر لسٹ کا URL", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { - "message": "Import / Export", + "message": "درآمد / برآمد", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "Paste here specific cosmetic/scriptlet filters to add", + "message": "شامل کرنے کے لیے مخصوص کاسمیٹک/اسکرپٹلیٹ فلٹرز", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "اپنے براؤزر کے ایکسٹینشنز پیج (chrome://extensions Chrome میں یا about:addons Firefox میں) کو کھولیں، uBO Lite کی تفصیلات کھولیں، اور Allow user scripts کو آن کریں (جسے “unverified third-party scripts” بھی کہا جاتا ہے)۔", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "چینج لاگ", "description": "" @@ -124,71 +148,71 @@ "description": "Shown in the About pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "فلٹر کا مسئلہ رپورٹ کریں", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "مخصوص ویب سائٹس کے ساتھ فلٹر کے مسائل کو uBlockOrigin/uAssets ایشو ٹریکر کو رپورٹ کریں۔ GitHub اکاؤنٹ درکار ہے۔", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting information", + "message": "خرابیوں کا ازالہ کرنے کی معلومات", "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "رضاکاروں کو نقلی رپورٹوں سے بوجھل کرنے سے بچنے کے لیے، براہ کرم تصدیق کریں کہ مسئلہ پہلے سے رپورٹ نہیں کیا گیا ہے۔ نوٹ: بٹن پر کلک کرنے سے صفحے کا ماخذ GitHub کو بھیج دیا جائے گا۔", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "GitHub پر مماثل رپورٹیں تلاش کریں", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "ویب صفحے کا پتہ:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "ویب صفحہ…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- ایک اندراج منتخب کریں --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "اشتہارات یا اشتہارات کی باقیات دکھاتا ہے", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "اوورلے یا دیگر پریشانیاں ہیں", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBO Lite", + "message": "uBO Lite کا پتہ لگاتا ہے", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "رازداری سے متعلق مسائل ہیں", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBO Lite is enabled", + "message": "جب uBO Lite فعال ہو تو خرابی پیدا کرتا ہے", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "نادیدہ ٹیبز یا ونڈوز کھولتا ہے", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "بیڈویئر، فشنگ کی طرف لے جاتا ہے", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "ویب صفحے کو “NSFW” کا لیبل لگائیں (“Not Safe For Work”)", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "GitHub پر نئی رپورٹ بنائیں", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { @@ -232,7 +256,7 @@ "description": "A short description for the editable field which lists trusted sites" }, "noFilteringModePlaceholder": { - "message": "[hostnames only]\nexample.com\ngames.example\n...", + "message": "[صرف ہوسٹ نام]\nexample.com\ngames.example\n...", "description": "Default text for in edit field" }, "behaviorSectionLabel": { @@ -248,175 +272,191 @@ "description": "Label for a checkbox in the options page" }, "enableStrictBlockLabel": { - "message": "Enable strict blocking", + "message": "سخت بلاکنگ کو فعال کریں", "description": "Label for a checkbox in the options page" }, "enableStrictBlockLegend": { - "message": "Navigation to potentially undesirable sites will be blocked, and you will be offered the option to proceed.", + "message": "ممکنہ طور پر ناپسندیدہ سائٹس پر نیویگیشن کو مسدود کر دیا جائے گا، اور آپ کو آگے بڑھنے کا اختیار دیا جائے گا۔", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "پاپ اپ بلاکنگ کو فعال کریں", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "جب فعال ہو، مماثل فلٹرز ویب سائٹس کے ذریعے بنائے گئے ناپسندیدہ براؤزر ٹیبز کو خودکار طور پر بند کر دیں گے۔", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "فلٹر تخلیق سینڈ باکس", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { - "message": "Developer mode", + "message": "ڈویلپر موڈ", "description": "Label for a checkbox in the options page" }, "developerModeLegend": { - "message": "Enables access to features suitable for technical users.", + "message": "تکنیکی صارفین کے لیے موزوں خصوصیات تک رسائی کو قابل بناتا ہے۔", "description": "Short description for a checkbox in the options page" }, "settingsBackupRestoreLabel": { - "message": "Backup", + "message": "بیک اپ", "description": "The header text for the back up/restore section" }, "settingsBackupRestoreSummary": { - "message": "Back up your custom settings to a file, or restore your custom settings from a file.", + "message": "اپنی حسب ضرورت ترتیبات کو فائل میں بیک اپ کریں، یا فائل سے اپنی حسب ضرورت ترتیبات بحال کریں۔", "description": "A summary description of the back up/restore section." }, "settingsBackupRestoreLegend": { - "message": "Restoring will overwrite all your current custom settings.", + "message": "بحال کرنے سے آپ کی تمام موجودہ حسب ضرورت ترتیبات تبدیل ہو جائیں گی۔", "description": "Important information about the back up/restore section." }, "findListsPlaceholder": { - "message": "Find lists", + "message": "فہرستیں تلاش کریں", "description": "Placeholder for the input field used to find lists" }, "strictblockTitle": { - "message": "Page blocked", + "message": "صفحہ مسدود ہے", "description": "Web page title for the strict-blocked page" }, "strictblockSentence1": { - "message": "uBO Lite has prevented the following page from loading:", + "message": "uBO Lite نے درج ذیل صفحہ کو لوڈ ہونے سے روک دیا ہے:", "description": "Sentence used in the strict-blocked page" }, "strictblockReasonSentence1": { - "message": "The page was blocked because of a matching filter in {{listname}}.", + "message": "صفحہ {{listname}} میں مماثل فلٹر کی وجہ سے مسدود کیا گیا تھا۔", "description": "Text informing about what is causing the page to be blocked" }, "strictblockRedirectSentence1": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "مسدود صفحہ کسی دوسری سائٹ پر ری ڈائریکٹ کرنا چاہتا ہے۔ اگر آپ آگے بڑھنے کا انتخاب کرتے ہیں، تو آپ براہ راست اس پر تشریف لے جائیں گے: {{url}}", "description": "Text warning about an incoming redirect" }, "strictblockNoParamsPrompt": { - "message": "without parameters", + "message": "پیرامیٹرز کے بغیر", "description": "Label to be used for the parameter-less URL" }, "strictblockBack": { - "message": "Go back", + "message": "واپس جائیں", "description": "A button to go back to the previous web page" }, "strictblockClose": { - "message": "Close this window", + "message": "یہ ونڈو بند کریں", "description": "A button to close the current tab" }, "strictblockDontWarn": { - "message": "Don't warn me again about this site", + "message": "مجھے اس سائٹ کے بارے میں دوبارہ خبردار نہ کریں", "description": "Label for checkbox in document-blocked page" }, "strictblockProceed": { - "message": "Proceed", + "message": "آگے بڑھیں", "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "Remove an element", + "message": "ایک عنصر ہٹائیں", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { - "message": "Exit element zapper mode", + "message": "عنصر زاپر موڈ سے باہر نکلیں", "description": "Tooltip for the button used to exit zapper mode" }, "pickerTipEnter": { - "message": "Create a custom filter", + "message": "حسب ضرورت فلٹر بنائیں", "description": "Label for the menu entry to create cosmetic filters" }, "unpickerTipEnter": { - "message": "Remove a custom filter", + "message": "حسب ضرورت فلٹر ہٹائیں", "description": "Label for the menu entry to delete cosmetic filters" }, "developDropdownLabel": { - "message": "View:", + "message": "دیکھیں:", "description": "A label of a dropdown list" }, "developOptionFilteringModeDetails": { - "message": "Filtering mode details", + "message": "فلٹرنگ موڈ کی تفصیلات", "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "Custom DNR rules", + "message": "حسب ضرورت DNR قواعد", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR rules of …", + "message": "کے DNR قواعد …", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { - "message": "Dynamic ruleset", + "message": "متحرک قواعد کا مجموعہ", "description": "An option in a dropdown list" }, "developOptionSessionRuleset": { - "message": "Session ruleset", + "message": "سیشن قواعد کا مجموعہ", "description": "An option in a dropdown list" }, "saveButton": { - "message": "Save", + "message": "محفوظ کریں", "description": "Text for buttons used to save changes" }, "revertButton": { - "message": "Revert", + "message": "واپس جائیں", "description": "Text for buttons used to revert changes" }, "addButton": { - "message": "Add", + "message": "شامل کریں", "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "Import and append…", + "message": "درآمد کریں اور منسلک کریں…", "description": "Text for buttons used to import and append content" }, "exportButton": { - "message": "Export…", + "message": "برآمد کریں…", "description": "Text for buttons used to export content" }, "backupButton": { - "message": "Back up…", + "message": "بیک اپ کریں…", "description": "Text for buttons used to back up content" }, "restoreButton": { - "message": "Restore…", + "message": "بحال کریں…", "description": "Text for buttons used to restore content" }, "resetToDefaultButton": { - "message": "Reset to default settings…", + "message": "پہلے سے طے شدہ ترتیبات پر ری سیٹ کریں…", "description": "Text for buttons used to reset configurations to default" }, "resetToDefaultConfirm": { - "message": "All your custom settings will be removed. Do you really want to reset to default settings?", + "message": "آپ کی تمام حسب ضرورت ترتیبات ہٹا دی جائیں گی۔ کیا آپ واقعی پہلے سے طے شدہ ترتیبات پر ری سیٹ کرنا چاہتے ہیں؟", "description": "Message asking user to confirm reset to default settings" }, "dnrRulesWarning": { - "message": "Do not add content from untrusted sources", + "message": "ناقابل اعتماد ذرائع سے مواد شامل نہ کریں", "description": "Short description of the DNR rules editor pane" }, "dnrRulesCountInfo": { - "message": "Number of registered rules: {count}", + "message": "رجسٹرڈ قواعد کی تعداد: {count}", "description": "Short sentence to report the number of currently registered DNR rules" }, "pickerSliderLabel": { - "message": "Move the slider to select the best match", + "message": "بہترین مماثلت منتخب کرنے کے لیے سلائیڈر کو منتقل کریں", "description": "Label to describe the purpose of the slider" }, "pickerPick": { - "message": "Pick", + "message": "منتخب کریں", "description": "Text for the button to re-enter element-picking mode" }, "pickerPreview": { - "message": "Preview", + "message": "پیش منظر", "description": "Text for the button to activate preview mode" }, "pickerCreate": { - "message": "Create", + "message": "بنائیں", "description": "Text for the button to create the filter" }, "unpickerUsage": { - "message": "Select a filter below to highlight matching elements in the web page. Click the trash can to remove a filter.", + "message": "ویب صفحے میں مماثل عناصر کو نمایاں کرنے کے لیے نیچے دیے گئے فلٹر کو منتخب کریں۔ فلٹر کو ہٹانے کے لیے کوڑے دان پر کلک کریں۔", "description": "Summary description on how to use the tool to remove custom filters" } } diff --git a/platform/mv3/extension/_locales/vi/messages.json b/platform/mv3/extension/_locales/vi/messages.json index eed12ff7014bf..054595963316d 100644 --- a/platform/mv3/extension/_locales/vi/messages.json +++ b/platform/mv3/extension/_locales/vi/messages.json @@ -35,6 +35,10 @@ "message": "Chính sách bảo mật", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "Tài liệu hướng dẫn", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "chế độ lọc", "description": "Label in the popup panel for the current filtering mode" @@ -87,6 +91,22 @@ "message": "Khu vực, ngôn ngữ", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "Danh sách đã nhập", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "Thêm danh sách bộ lọc…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "URL của danh sách bộ lọc cần thêm", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "Để áp dụng các bộ lọc trong danh sách đã nhập, bạn phải cấp cho uBO Lite quyền thực thi 'các tập lệnh người dùng'.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "Nhập / Xuất", "description": "Text label heading the import/export area of custom filters" @@ -95,6 +115,10 @@ "message": "Dán vào đây các bộ lọc cụ thể để thêm", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "Mở trang tiện ích mở rộng của trình duyệt (chrome://extensions trong Chrome hoặc about:addons trong Firefox), mở chi tiết uBO Lite và bật Cho phép tập lệnh người dùng (còn được gọi là “tập lệnh của bên thứ ba chưa được xác minh”).", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "Nhật ký thay đổi", "description": "" @@ -255,6 +279,22 @@ "message": "Việc điều hướng đến các trang web có khả năng không mong muốn sẽ bị chặn và bạn sẽ được cung cấp tùy chọn để tiếp tục.", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "Bật tính năng chặn cửa sổ bật lên", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "Khi được kích hoạt, các bộ lọc phù hợp sẽ tự động đóng các tab trình duyệt không mong muốn do các trang web tạo ra.", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "Hộp thử nghiệm tạo bộ lọc", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "Để áp dụng các bộ lọc trong hộp thử nghiệm, bạn phải cấp cho uBO Lite quyền thực thi 'các tập lệnh người dùng'.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "Chế độ nhà phát triển", "description": "Label for a checkbox in the options page" diff --git a/platform/mv3/extension/_locales/zh_CN/messages.json b/platform/mv3/extension/_locales/zh_CN/messages.json index 7754478f911b0..fb8f0b6b5a557 100644 --- a/platform/mv3/extension/_locales/zh_CN/messages.json +++ b/platform/mv3/extension/_locales/zh_CN/messages.json @@ -8,7 +8,7 @@ "description": "this will be in the Chrome web store: must be 132 characters or less" }, "perRulesetStats": { - "message": "{{ruleCount}} 条规则,转换自 {{filterCount}} 条网络共享规则", + "message": "{{ruleCount}} 条规则,转换自 {{filterCount}} 条网络规则", "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "dashboardName": { @@ -35,16 +35,20 @@ "message": "隐私政策", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "文档", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "过滤模式", "description": "Label in the popup panel for the current filtering mode" }, "popupLocalToolsLabel": { - "message": "在本网站上", + "message": "针对此网站", "description": "Label in the popup panel for the local tools section" }, "popupTipReport": { - "message": "报告此网站上的问题", + "message": "反馈问题", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipDashboard": { @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "恶意网站", + "message": "恶意软件防护,安全", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -84,17 +88,37 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupRegions": { - "message": "区域、语言", + "message": "区域/语言", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "3pGroupImported": { + "message": "已导入的列表", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "customListImportLabel": { + "message": "添加过滤列表…", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "在此处粘贴要添加的过滤列表的 URL", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from imported lists, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "导入/导出", "description": "Text label heading the import/export area of custom filters" }, "customFiltersImportTextareaPlaceholder": { - "message": "在此粘贴要添加的特定元素过滤规则", + "message": "在此处粘贴要添加的特定元素/脚本过滤规则", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "打开浏览器的扩展页面(Chrome 中为 chrome://extensions,Firefox 中为 about:addons),打开 uBO Lite 详情,然后开启 允许用户脚本(也称为“未经验证的第三方脚本”)。", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "更新日志", "description": "" @@ -124,7 +148,7 @@ "description": "Shown in the About pane" }, "supportS6H": { - "message": "报告过滤问题", + "message": "反馈过滤规则问题", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS3P1": { @@ -132,15 +156,15 @@ "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS5H": { - "message": "故障排查相关信息", + "message": "故障排查信息", "description": "Label of 'Troubleshooting information' section in 'Report a filter issue' page" }, "supportS6P1S1": { - "message": "请确认该问题未曾上报,以避免加重志愿者负担。", + "message": "请确认该问题未曾上报,以避免加重志愿者负担。\n备注:点击此按钮会将此页面的 origin(协议+域名+端口)发送到 GitHub。(译注:以便编写问题报告)", "description": "A paragraph in the filter issue reporter section" }, "supportFindSpecificButton": { - "message": "在 GitHub 上寻找相似报告", + "message": "在 GitHub 上查找相似报告", "description": "A clickable link in the filter issue reporter section" }, "supportS6URL": { @@ -180,15 +204,15 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "导致恶意软件、网络钓鱼", + "message": "引向恶意软件、网络钓鱼", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "将网页标记为 “NSFW”(“工作场所不宜”)", + "message": "将网页标记为 “NSFW”(“工作场所不宜”)", "description": "A checkbox to use for NSFW sites" }, "supportReportSpecificButton": { - "message": "创建新报告", + "message": "前往 GitHub 创建新报告", "description": "Text for button which opens an external web page in Support pane" }, "defaultFilteringModeSectionLabel": { @@ -255,6 +279,22 @@ "message": "导航至潜在不良网站的操作将被拦截,并且您将可以选择继续前往。", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "开启弹出窗口拦截", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "开启后,匹配的过滤器将自动关闭网站创建的不需要的浏览器标签页。", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "过滤器创建沙盒", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "To enforce cosmetic or scriptlet filters from the sandbox, you must grant uBO Lite permission to run user scripts.", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "开发者模式", "description": "Label for a checkbox in the options page" @@ -340,11 +380,11 @@ "description": "An option in a dropdown list" }, "developOptionCustomDnrRules": { - "message": "自定义DNR规则", + "message": "自定义 DNR 规则", "description": "An option in a dropdown list" }, "developOptionDnrRulesOf": { - "message": "DNR规则来源:", + "message": "DNR 规则来源:", "description": "A section header in a dropdown list" }, "developOptionDynamicRuleset": { @@ -368,7 +408,7 @@ "description": "Text for buttons used to add content" }, "importAndAppendButton": { - "message": "导入并添加…", + "message": "导入并追加…", "description": "Text for buttons used to import and append content" }, "exportButton": { diff --git a/platform/mv3/extension/_locales/zh_TW/messages.json b/platform/mv3/extension/_locales/zh_TW/messages.json index f8cc378afbe0a..4806cc07f762a 100644 --- a/platform/mv3/extension/_locales/zh_TW/messages.json +++ b/platform/mv3/extension/_locales/zh_TW/messages.json @@ -35,6 +35,10 @@ "message": "隱私權政策", "description": "Link to privacy policy on GitHub (English)" }, + "aboutDocumentation": { + "message": "文件", + "description": "Link to documentation in About pane" + }, "popupFilteringModeLabel": { "message": "過濾模式", "description": "Label in the popup panel for the current filtering mode" @@ -72,7 +76,7 @@ "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupMalware": { - "message": "惡意網域", + "message": "惡意軟體防護與安全性", "description": "Header for a ruleset section in 'Filter lists pane'" }, "3pGroupAnnoyances": { @@ -87,6 +91,22 @@ "message": "地區及語言", "description": "Header for a ruleset section in 'Filter lists pane'" }, + "3pGroupImported": { + "message": "已導入的清單", + "description": "Header for a ruleset section in 'Filter lists pane'" + }, + "customListImportLabel": { + "message": "添加過濾清單……", + "description": "Text label heading the import area of custom filter lists" + }, + "customListImportPlaceholder": { + "message": "要添加的過濾清單url", + "description": "Placeholder text which describes the purpose of the textarea widget" + }, + "customListImportUserScriptsInfo": { + "message": "若要套用從匯入清單中的樣式或小令稿過濾規則,您必須授予 uBO Lite 執行使用者命令稿的權限。", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "customFiltersImportExportLabel": { "message": "匯入 / 匯出", "description": "Text label heading the import/export area of custom filters" @@ -95,6 +115,10 @@ "message": "在這裡貼上要新增的元素隱藏篩選規則", "description": "Placeholder text which describes the purpose of the textarea widget" }, + "userScriptsInfo": { + "message": "請開啟瀏覽器的擴充功能頁面(Chrome 中輸入 chrome://extensions,Firefox 中輸入 about:addons),開啟 uBO Lite 的詳細資料,並啟用允許使用者腳本(亦稱為『未經驗證的第三方腳本』)。", + "description": "A notice to inform user on how to enable 'user scripts' permission" + }, "aboutChangelog": { "message": "變更日誌", "description": "" @@ -255,6 +279,22 @@ "message": "前往潛在不良網站的導航將被阻止,您可以選擇是否繼續前往。", "description": "Short description for a checkbox in the options page" }, + "enablePopupBlockLabel": { + "message": "啟用彈出式視窗封鎖", + "description": "Label for a checkbox in the options page" + }, + "enablePopupBlockLegend": { + "message": "啟用後,符合的篩選規則將自動關閉網站所建立的不需要的瀏覽器分頁。", + "description": "Short description for a checkbox in the options page" + }, + "sandboxEditorLabel": { + "message": "篩選規則建立沙盒", + "description": "Header for filter-creation section in the dashboard" + }, + "sandboxEditorUserScriptsInfo": { + "message": "若要在沙盒中套用外觀或小令稿過濾規則,您必須授予 uBO Lite 執行使用者命令稿的權限。", + "description": "A notice to inform user that the enforcement of some filters requires permission to execute 'user scripts'" + }, "developerModeLabel": { "message": "開發人員模式", "description": "Label for a checkbox in the options page" @@ -316,7 +356,7 @@ "description": "A button to navigate to the blocked page" }, "zapperTipEnter": { - "message": "進入元素臨時移除模式", + "message": "移除元素", "description": "Tooltip for the button used to enter zapper mode" }, "zapperTipQuit": { diff --git a/platform/mv3/extension/css/dashboard-common.css b/platform/mv3/extension/css/dashboard-common.css index d88e12cd6a03a..f3af987bb967f 100644 --- a/platform/mv3/extension/css/dashboard-common.css +++ b/platform/mv3/extension/css/dashboard-common.css @@ -21,6 +21,9 @@ h3 { a { text-decoration: none; } +summary { + cursor: pointer; + } .fa-icon.info { color: var(--info0-ink); diff --git a/platform/mv3/extension/css/develop.css b/platform/mv3/extension/css/develop.css index 3f165443e04eb..864f329eed199 100644 --- a/platform/mv3/extension/css/develop.css +++ b/platform/mv3/extension/css/develop.css @@ -12,6 +12,7 @@ section[data-pane="develop"] > div { display: flex; flex-direction: column; height: 100%; + overflow: hidden; } section[data-pane="develop"] > div > * { @@ -19,57 +20,58 @@ section[data-pane="develop"] > div > * { margin-top: 1em; } -#cm-container { +.cm-container { flex-grow: 1; font-size: var(--monospace-size); - overflow: hidden; + height: 90%; + padding-bottom: 2em; } /* https://discuss.codemirror.net/t/how-to-set-max-height-of-the-editor/2882/2 */ -#cm-container .cm-editor { +.cm-container .cm-editor { background-color: var(--surface-0); height: 100%; } -#cm-container .cm-editor .cm-line:has(.ubol-boundary) { +.cm-container .cm-editor .cm-line:has(.ubol-boundary) { background-image: url('line-hor-dashed.png'), url('line-hor-dashed.png'); background-position: left 3px, left calc(100% - 3px); background-repeat: repeat-x; } -#cm-container .cm-editor { +.cm-container .cm-editor { color: var(--ink-1); } -:root.dark #cm-container .cm-editor { +:root.dark .cm-container .cm-editor { color: var(--ink-2); } -#cm-container .cm-editor .cm-line .ubol-comment { +.cm-container .cm-editor .cm-line .ubol-comment { color: #ba5300; } -:root.dark #cm-container .cm-editor .cm-line .ubol-comment { +:root.dark .cm-container .cm-editor .cm-line .ubol-comment { color: #fa7000; } -#cm-container .cm-editor .cm-line .ubol-keyword { +.cm-container .cm-editor .cm-line .ubol-keyword { color: #ae42be; } -:root.dark #cm-container .cm-editor .cm-line .ubol-keyword { +:root.dark .cm-container .cm-editor .cm-line .ubol-keyword { color: #ea59ff; } -#cm-container .cm-editor .cm-line .ubol-literal { +.cm-container .cm-editor .cm-line .ubol-literal { color: #168156; } -:root.dark #cm-container .cm-editor .cm-line .ubol-literal { +:root.dark .cm-container .cm-editor .cm-line .ubol-literal { color: #1dae74; } -#cm-container .cm-editor .cm-line.badline { +.cm-container .cm-editor .cm-line.badline { background-color: color-mix(in srgb, var(--info3-ink) 15%, transparent 85%); } -#cm-container .cm-editor .cm-line .badmark { +.cm-container .cm-editor .cm-line .badmark { text-decoration: underline var(--cm-negative) wavy; text-decoration-skip-ink: none; } -#cm-container .cm-editor .cm-panel.cm-search { +.cm-container .cm-editor .cm-panel.cm-search { display: flex; flex-wrap: wrap; font-family: sans-serif; @@ -78,13 +80,13 @@ section[data-pane="develop"] > div > * { padding: 0.5em 1.5em 0.5em 0.5em; } -#cm-container .cm-editor .cm-panel.cm-search > * { +.cm-container .cm-editor .cm-panel.cm-search > * { margin: 0; } -#cm-container .cm-editor .cm-panel.cm-search .cm-textfield, -#cm-container .cm-editor .cm-panel.cm-search .cm-button, -#cm-container .cm-editor .cm-panel.cm-search label { +.cm-container .cm-editor .cm-panel.cm-search .cm-textfield, +.cm-container .cm-editor .cm-panel.cm-search .cm-button, +.cm-container .cm-editor .cm-panel.cm-search label { background-image: inherit; border: inherit; flex-grow: 0; @@ -92,11 +94,11 @@ section[data-pane="develop"] > div > * { min-height: calc(var(--button-font-size) * 1.8); } -#cm-container .cm-editor .cm-panel .warning { +.cm-container .cm-editor .cm-panel .warning { color: var(--info3-ink); } -#cm-container .cm-editor .cm-panel.io-panel { +.cm-container .cm-editor .cm-panel.io-panel { background-color: var(--surface-1); box-sizing: border-box; display: inline-flex; @@ -105,64 +107,64 @@ section[data-pane="develop"] > div > * { padding-inline-start: 0; width: 100%; } -#cm-container .cm-editor .cm-panel.io-panel button { +.cm-container .cm-editor .cm-panel.io-panel button { min-height: 30px; } -#cm-container .cm-editor .cm-panel.io-panel button#revert { +.cm-container .cm-editor .cm-panel.io-panel button#revert { margin-inline-end: 1em; } -#cm-container .cm-editor .cm-panel.io-panel:not([data-io~="apply"]) button#apply { +.cm-container .cm-editor .cm-panel.io-panel:not([data-io~="apply"]) button#apply { display: none; } -#cm-container .cm-editor .cm-panel.io-panel:not([data-io~="revert"]) button#revert { +.cm-container .cm-editor .cm-panel.io-panel:not([data-io~="revert"]) button#revert { display: none; } -#cm-container .cm-editor .cm-panel.io-panel:not([data-io~="import"]) button#import { +.cm-container .cm-editor .cm-panel.io-panel:not([data-io~="import"]) button#import { display: none; } -#cm-container .cm-editor .cm-panel.io-panel:not([data-io~="export"]) button#export { +.cm-container .cm-editor .cm-panel.io-panel:not([data-io~="export"]) button#export { display: none; } -#cm-container .cm-editor .cm-panel.info-panel { +.cm-container .cm-editor .cm-panel.info-panel { display: flex; flex-wrap: nowrap; font-size: var(--font-size); padding: var(--default-gap-xxsmall) var(--default-gap-xsmall); } -#cm-container .cm-editor .cm-panel.info-panel .info { +.cm-container .cm-editor .cm-panel.info-panel .info { flex-grow: 1; overflow: auto; } -#cm-container .cm-editor .cm-panel.info-panel .close { +.cm-container .cm-editor .cm-panel.info-panel .close { cursor: default; flex-shrink: 0; padding-inline-start: 1em; } -#cm-container .cm-editor .cm-panel.info-panel .close::after { +.cm-container .cm-editor .cm-panel.info-panel .close::after { content: '\2715'; } -#cm-container .cm-editor .cm-panel.summary-panel { +.cm-container .cm-editor .cm-panel.summary-panel { background-color: color-mix(in srgb, var(--info1-ink) 15%, transparent 85%); gap: 1em; } -#cm-container .cm-editor .cm-panel.summary-panel .info { +.cm-container .cm-editor .cm-panel.summary-panel .info { flex-shrink: 0; } -#cm-container .cm-editor .cm-panel.feedback-panel { +.cm-container .cm-editor .cm-panel.feedback-panel { background-color: color-mix(in srgb, var(--info3-ink) 15%, transparent 85%); white-space: pre; max-height: 10cqh; } -#cm-container .cm-editor .cm-gutterElement { +.cm-container .cm-editor .cm-gutterElement { cursor: default; user-select: none; } -#cm-container .cm-editor .cm-tooltip .badmark-tooltip { +.cm-container .cm-editor .cm-tooltip .badmark-tooltip { background-color: color-mix(in srgb, var(--info3-ink) 15%, transparent 85%); padding: var(--default-gap-xxsmall) var(--default-gap-xsmall); } \ No newline at end of file diff --git a/platform/mv3/extension/css/filter-editor.css b/platform/mv3/extension/css/filter-editor.css new file mode 100644 index 0000000000000..187c501133146 --- /dev/null +++ b/platform/mv3/extension/css/filter-editor.css @@ -0,0 +1,52 @@ +.cm-container .cm-line { + word-break: break-all; + } +.sfp_comment { + color: var(--sf-comment-ink); + } +.sfp_def { + color: var(--sf-def-ink); + } +.sfp_directive { + color: var(--sf-directive-ink); + font-weight: bold; + } +.sfp_error { + color: inherit; + } +.sfp-ext-dom { + } +.sfp-ext-html { + } +.sfp-ext-js { + } +.sfp_keyword { + color: var(--sf-keyword-ink); + } +.sfp_link { + text-decoration: none; + } +.sfp-net { + } +.sfp_notice { + text-decoration-color: var(--sf-notice-ink); + text-decoration-style: solid; + text-decoration-line: underline; + } +.sfp_strong { + font-weight: bold; + } +.sfp_tag { + color: var(--sf-tag-ink); + } +.sfp_unicode { + text-decoration-color: var(--sf-unicode-ink); + text-decoration-style: dashed; + text-decoration-line: underline; + } +.sfp_value { + color: var(--sf-value-ink); + } +.sfp_variable { + color: var(--sf-variable-ink); + } diff --git a/platform/mv3/extension/css/filtering-mode.css b/platform/mv3/extension/css/filtering-mode.css index 2554bdc3ac385..fb27980b79ebe 100644 --- a/platform/mv3/extension/css/filtering-mode.css +++ b/platform/mv3/extension/css/filtering-mode.css @@ -1,6 +1,7 @@ :root { --filtering-mode-button-size: 60px; /* should be multiple of 4 */ --filtering-mode-slider-width: calc(4 * var(--filtering-mode-button-size) + 3px); + --filtering-mode-slider-background: var(--surface-3); } .filteringModeSlider { @@ -37,8 +38,8 @@ } .filteringModeSlider[data-level="0"] .filteringModeButton > div { - background-color: var(--surface-2); - border-color: var(--surface-2); + background-color: var(--filtering-mode-slider-background); + border-color: var(--filtering-mode-slider-background); } .filteringModeSlider span[data-level] { @@ -92,18 +93,18 @@ .filteringModeSlider[data-level="0"] span[data-level] { - background-color: var(--surface-2); - border-color: var(--surface-2); + background-color: var(--filtering-mode-slider-background); + border-color: var(--filtering-mode-slider-background); } .filteringModeSlider[data-level="1"] span[data-level]:nth-of-type(1) ~ span[data-level] { - background-color: var(--surface-2); - border-color: var(--surface-2); + background-color: var(--filtering-mode-slider-background); + border-color: var(--filtering-mode-slider-background); } .filteringModeSlider[data-level="2"] span[data-level]:nth-of-type(2) ~ span[data-level] { - background-color: var(--surface-2); - border-color: var(--surface-2); + background-color: var(--filtering-mode-slider-background); + border-color: var(--filtering-mode-slider-background); } .filteringModeSlider[data-level]:not(.moving) span[data-level]:hover { diff --git a/platform/mv3/extension/css/settings.css b/platform/mv3/extension/css/settings.css index 8dfae49cbd8c5..d340324bb5398 100644 --- a/platform/mv3/extension/css/settings.css +++ b/platform/mv3/extension/css/settings.css @@ -17,7 +17,12 @@ body.loading { h3 { margin: 1em 0; } - +input, select { + min-height: 30px; + } +aside { + margin-block-start: 1em; + } label + legend { color: color-mix(in srgb, currentColor 69%, transparent); font-size: var(--font-size-smaller); @@ -140,6 +145,9 @@ section[data-pane="rulesets"] > div:first-of-type > p:last-of-type { .listEntry[data-role="rootnode"] > .detailbar > *:not(.listExpander) { pointer-events: none; } +.listEntry[data-role="rootnode"]:not([data-nodeid="imported"]):has(> .listEntries:empty) { + display: none; + } .listEntry .detailbar .count { align-self: flex-end; color: var(--ink-3); @@ -198,9 +206,23 @@ section[data-pane="rulesets"] > div:first-of-type > p:last-of-type { .listEntry .fa-icon:hover { transform: scale(1.25); } -.listEntry .iconbar a.support[href="#"] { +.listEntry[data-role="leaf"] .iconbar { + display: inline-flex; + gap: 0.25em; + } +.listEntry[data-role="leaf"] .iconbar a.support[href="#"] { display: none; } +.listEntry[data-role="leaf"]:not([data-imported]) .doRemove, +.listEntry[data-role="leaf"]:not([data-imported]) .undoRemove, +.listEntry[data-role="leaf"][data-imported][data-remove] .doRemove, +.listEntry[data-role="leaf"][data-imported]:not([data-remove]) .undoRemove { + display: none; + } +.listEntry[data-role="leaf"][data-imported][data-remove] { + text-decoration: line-through 2px red; + } + body.noMoreRuleset .listEntry:has(> .detailbar input:not(:checked)) { opacity: 0.5; @@ -221,7 +243,6 @@ body.noMoreRuleset .listEntry:has(> .detailbar input:not(:checked)) { /* touch-screen devices */ :root.mobile .listEntry .fa-icon { font-size: 120%; - margin: 0 0.5em 0 0; } :root.mobile .listEntries { margin-inline-start: 0; @@ -243,6 +264,31 @@ body.noMoreRuleset .listEntry:has(> .detailbar input:not(:checked)) { margin-top: 0.2em; } +body:not([data-supports~="compiled-filters"]) section[data-pane="rulesets"] aside, +body:not([data-supports~="compiled-filters"]) section[data-pane="rulesets"] #lists [data-role="rootnode"][data-nodeid="imported"] { + display: none; + } +section[data-pane="rulesets"] #lists:has([data-nodeid="imported"].hideUnused) + aside { + display: none; +} +body .userScriptsInfo { + color: var(--ink-2); + font-size: small; + } +body[data-supports~="user-scripts"] .userScriptsInfo { + display: none; + } +body section[data-pane="rulesets"] .importRulesetURL > p { + display: flex; + gap: 1em; + } +body section[data-pane="rulesets"] .importRulesetURL input { + flex-grow: 1; + } +body section[data-pane="rulesets"] .importRulesetURL input:is(:placeholder-shown,:invalid) ~ button { + display: none; + } + body section[data-pane="filters"] { padding-inline: 0; } @@ -320,20 +366,16 @@ html.desktop section[data-pane="filters"] li > div:hover { html.desktop section[data-pane="filters"] li > div span.fa-icon:hover { transform: scale(1.3); } -section[data-pane="filters"] aside { - padding: 1em 0.5em; - } section[data-pane="filters"] aside details { - padding: 0; + padding: 1em 0; } section[data-pane="filters"] aside summary { - cursor: default; line-height: 2; } section[data-pane="filters"] aside .importFromText { color: var(--ink-2); } -section[data-pane="filters"] aside .importFromText textarea { +section[data-pane="filters"] aside textarea { background-color: var(--surface-1); border: 1px solid var(--border-1); box-sizing: border-box; @@ -341,7 +383,7 @@ section[data-pane="filters"] aside .importFromText textarea { resize: vertical; width: 100%; } -section[data-pane="filters"] aside .importFromText textarea:focus { +section[data-pane="filters"] aside textarea:focus { background-color: var(--surface-0); } section[data-pane="filters"] aside .importFromText:has(textarea:placeholder-shown) button:has([data-i18n="addButton"]) { @@ -351,7 +393,7 @@ section[data-pane="filters"] aside .importFromText:not(:has(textarea:placeholder section[data-pane="filters"] aside .importFromText:not(:has(textarea:placeholder-shown)) button:has([data-i18n="exportButton"]) { display: none; } -section[data-pane="filters"] aside p { +section[data-pane="filters"] aside .importFromText p { display: flex; flex-wrap: wrap; gap: 1em; @@ -359,6 +401,13 @@ section[data-pane="filters"] aside p { section[data-pane="filters"] li.error[data-pretty] > div span[contenteditable] { color: var(--info3-ink); } +body:not([data-supports~="compiled-filters"]) section[data-pane="filters"] aside#sandboxEditor { + display: none; + } +section[data-pane="filters"] aside#sandboxEditor .cm-scroller { + min-height: 120px; + max-height: 480px; + } @media (max-width: 480px) { #defaultFilteringMode { diff --git a/platform/mv3/extension/dashboard.html b/platform/mv3/extension/dashboard.html index 5300d62158fb5..8b5fcecaccaa2 100644 --- a/platform/mv3/extension/dashboard.html +++ b/platform/mv3/extension/dashboard.html @@ -13,6 +13,7 @@ + @@ -97,6 +98,7 @@

+

@@ -113,6 +115,15 @@

_

+
@@ -128,6 +139,11 @@

_

+ @@ -144,7 +160,7 @@

_

 

-
+
@@ -156,6 +172,7 @@

_

Copyright (c) Raymond Hill 2014-present
+
@@ -171,6 +188,7 @@

_

+
@@ -193,6 +211,8 @@

_

trash-oundohome diff --git a/platform/mv3/extension/js/admin.js b/platform/mv3/extension/js/admin.js index 107cd2024861b..94ff9b763cdc7 100644 --- a/platform/mv3/extension/js/admin.js +++ b/platform/mv3/extension/js/admin.js @@ -21,12 +21,13 @@ import { adminRead, - localRead, localRemove, localWrite, + localRead, localWrite, sessionRead, sessionWrite, } from './ext.js'; import { enableRulesets, + getEnabledRulesets, getRulesetDetails, setStrictBlockMode, } from './ruleset-manager.js'; @@ -43,20 +44,23 @@ import { import { broadcastMessage } from './utils.js'; import { dnr } from './ext-compat.js'; -import { registerInjectables } from './scripting-manager.js'; +import { registerContentScripts } from './scripting-manager.js'; +import { setPopupBlockMode } from './prevent-popup.js'; import { ubolLog } from './debug.js'; /******************************************************************************/ export async function loadAdminConfig() { const [ + popupBlockMode, showBlockedCount, strictBlockMode, ] = await Promise.all([ + adminReadEx('popupBlockMode'), adminReadEx('showBlockedCount'), adminReadEx('strictBlockMode'), ]); - applyAdminConfig({ showBlockedCount, strictBlockMode }); + applyAdminConfig({ popupBlockMode, showBlockedCount, strictBlockMode }); } /******************************************************************************/ @@ -75,6 +79,13 @@ function applyAdminConfig(config, apply = false) { while ( toApply.length !== 0 ) { const key = toApply.pop(); switch ( key ) { + case 'popupBlockMode': { + const { popupBlockMode } = config; + setPopupBlockMode(popupBlockMode, true).then(( ) => { + broadcastMessage({ popupBlockMode }); + }); + break; + } case 'showBlockedCount': { if ( typeof dnr.setExtensionActionOptions !== 'function' ) { break; } const { showBlockedCount } = config; @@ -114,10 +125,10 @@ const adminSettings = { if ( this.keys.has('rulesets') ) { ubolLog('admin setting "rulesets" changed'); await enableRulesets(rulesetConfig.enabledRulesets); - await registerInjectables(); + await registerContentScripts(); const results = await Promise.all([ getAdminRulesets(), - dnr.getEnabledRulesets(), + getEnabledRulesets(), ]); const [ adminRulesets, enabledRulesets ] = results; broadcastMessage({ adminRulesets, enabledRulesets }); @@ -125,16 +136,22 @@ const adminSettings = { if ( this.keys.has('defaultFiltering') ) { ubolLog('admin setting "defaultFiltering" changed'); await readFilteringModeDetails(true); - await registerInjectables(); + await registerContentScripts(); const defaultFilteringMode = await getDefaultFilteringMode(); broadcastMessage({ defaultFilteringMode }); } if ( this.keys.has('noFiltering') ) { ubolLog('admin setting "noFiltering" changed'); const filteringModeDetails = await readFilteringModeDetails(true); - await registerInjectables(); + await registerContentScripts(); broadcastMessage({ filteringModeDetails }); } + if ( this.keys.has('popupBlockMode') ) { + ubolLog('admin setting "popupBlockMode" changed'); + const popupBlockMode = this.keys.get('popupBlockMode'); + applyAdminConfig({ popupBlockMode }, true); + await registerContentScripts(); + } if ( this.keys.has('showBlockedCount') ) { ubolLog('admin setting "showBlockedCount" changed'); const showBlockedCount = this.keys.get('showBlockedCount'); @@ -199,7 +216,6 @@ export async function adminReadEx(key) { if ( local ) { cacheValue = local.data; } - localRemove(`admin_${key}`); // TODO: remove eventually } adminRead(key).then(async value => { const adminKey = `admin.${key}`; diff --git a/platform/mv3/extension/js/alarms.js b/platform/mv3/extension/js/alarms.js new file mode 100644 index 0000000000000..d08dc84b6c10d --- /dev/null +++ b/platform/mv3/extension/js/alarms.js @@ -0,0 +1,88 @@ +/******************************************************************************* + + uBlock Origin Lite - a comprehensive, MV3-compliant content blocker + Copyright (C) 2026-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock +*/ + +import { + browser, + localRead, localRemove, localWrite, +} from './ext.js'; + +import { ubolLog } from './debug.js'; + +/******************************************************************************/ + +function setupJobsAlarm(jobs) { + if ( Boolean(jobs?.length) === false ) { + return browser.alarms.clear('deferredJobs'); + } + // No less than 5 minutes in the future + const when = Math.max(jobs[0].time, Date.now() + 5 * 60 * 1000); + ubolLog(`Created alarm for ${(new Date(when)).toString()}`); + return browser.alarms.create('deferredJobs', { when }); +} + +export async function registerJob(name, time) { + const jobs = await localRead('deferredJobs') || []; + const job = jobs.find(a => a.name === name); + if ( job ) { + job.time = time; + } else { + jobs.push({ name, time }); + } + jobs.sort((a, b) => a.time - b.time); + setupJobsAlarm(jobs); + return localWrite('deferredJobs', jobs); +} + +export async function removeJob(name) { + const before = await localRead('deferredJobs'); + const after = before.filter(a => a.name !== name); + if ( after.length === before.length ) { return; } + setupJobsAlarm(after); + if ( after.length ) { + return localWrite('deferredJobs', after); + } + return localRemove('deferredJobs'); +} + +export async function processDueJobs(dispatcher) { + const jobs = await localRead('deferredJobs'); + if ( Boolean(jobs?.length) === false ) { return; } + const now = Date.now(); + let i = 0; + while ( i < jobs.length ) { + if ( jobs[i].time > now ) { break; } + i += 1; + } + const toProcess = jobs.slice(0, i); + const toDefer = jobs.slice(i); + if ( toDefer.length ) { + setupJobsAlarm(toDefer); + await localWrite('deferredJobs', toDefer); + } else { + await localRemove('deferredJobs'); + } + await Promise.all(toProcess.map(a => dispatcher({ what: a.name }))); +} + +export async function resetJobsAlarm() { + const jobs = await localRead('deferredJobs'); + setupJobsAlarm(jobs); +} diff --git a/platform/mv3/extension/js/background.js b/platform/mv3/extension/js/background.js index 6b7a0b550e452..e7eb34ea52c8d 100644 --- a/platform/mv3/extension/js/background.js +++ b/platform/mv3/extension/js/background.js @@ -19,8 +19,6 @@ Home: https://github.com/gorhill/uBlock */ -import * as scrmgr from './scripting-manager.js'; - import { MODE_BASIC, MODE_OPTIMAL, @@ -39,14 +37,23 @@ import { addCustomFilters, customFiltersFromHostname, getAllCustomFilters, + getSandboxFilters, hasCustomFilters, injectCustomFilters, removeAllCustomFilters, removeCustomFilters, + setSandboxFilters, startCustomFilters, terminateCustomFilters, } from './filter-manager.js'; +import { + addImportedLists, + getImportedLists, + removeImportedLists, + updateImportedLists, +} from './imported-lists.js'; + import { adminReadEx, getAdminRulesets, @@ -57,7 +64,7 @@ import { broadcastMessage, hostnameFromMatch, hostnamesFromMatches, - intFromVersion, + isScriptlet, } from './utils.js'; import { @@ -65,6 +72,7 @@ import { localRead, localRemove, localWrite, runtime, sessionAccessLevel, + supportsUserScripts, webextFlavor, } from './ext.js'; @@ -80,14 +88,14 @@ import { enableRulesets, excludeFromStrictBlock, getDefaultRulesetsFromEnv, - getEffectiveDynamicRules, - getEffectiveSessionRules, getEffectiveUserRules, + getEnabledRulesets, getEnabledRulesetsDetails, getRulesetDetails, + getRulesetRules, patchDefaultRulesets, setStrictBlockMode, - updateDynamicRules, + updateDynamicAndSessionRules, updateSessionRules, updateUserRules, } from './ruleset-manager.js'; @@ -101,19 +109,37 @@ import { ubolLog, } from './debug.js'; +import { + getRegisteredContentScripts, + pruneCSSCache, + registerContentScripts, +} from './scripting-manager.js'; + import { gotoURL, hasBroadHostPermissions, } from './ext-utils.js'; +import { + processDueJobs, + resetJobsAlarm, +} from './alarms.js'; + +import { + registerUserScripts, + updateCompiledFilters, +} from './compiled-filters.js'; + +import { deferredTasks } from './deferred-tasks.js'; import { dnr } from './ext-compat.js'; +import { setPopupBlockMode } from './prevent-popup.js'; +import { supportsOffscreenDocument } from './ext-offscreen.js'; import { toggleToolbarIcon } from './action.js'; /******************************************************************************/ const UBOL_ORIGIN = runtime.getURL('').replace(/\/$/, '').toLowerCase(); const canShowBlockedCount = typeof dnr.setExtensionActionOptions === 'function'; -const { registerInjectables } = scrmgr; let pendingPermissionRequest; @@ -150,7 +176,7 @@ async function onPermissionGrantedThruExtension(details, origins) { if ( beforeLevel === details.afterLevel ) { return; } const afterLevel = await setFilteringMode(details.hostname, details.afterLevel); if ( afterLevel !== details.afterLevel ) { return; } - await registerInjectables(); + await registerContentScripts(); if ( rulesetConfig.autoReload !== true ) { return; } await reloadTab(details.tabId, details.url); } @@ -159,7 +185,7 @@ async function onPermissionGrantedThruExtension(details, origins) { async function onPermissionGrantedThruBrowser(origins) { const modified = await syncWithBrowserPermissions(); if ( modified === false ) { return; } - await registerInjectables(); + await registerContentScripts(); if ( rulesetConfig.autoReload !== true ) { return; } if ( origins.length !== 1 ) { return; } const tabs = await browser.tabs.query({ active: true, currentWindow: true }); @@ -192,7 +218,7 @@ async function onPermissionsAdded(permissions) { async function onPermissionsRemoved() { const modified = await syncWithBrowserPermissions(); if ( modified === false ) { return false; } - registerInjectables(); + registerContentScripts(); return true; } @@ -209,210 +235,233 @@ onPermissionsChanged.pending = []; /******************************************************************************/ -function setDeveloperMode(state) { +async function applyRulesets(rulesets) { + const result = await enableRulesets(rulesets); + const stockUpdated = result.stockUpdated ?? false; + const importedUpdated = result.importedUpdated ?? false; + if ( stockUpdated || importedUpdated ) { + rulesetConfig.enabledRulesets = result.enabledRulesets; + await saveRulesetConfig(); + const promises = []; + if ( importedUpdated ) { + promises.push( + updateCompiledFilters().then(( ) => + Promise.all([ registerUserScripts(), updateUserRules() ]) + ) + ); + } + if ( stockUpdated ) { + promises.push(registerContentScripts()); + } + await Promise.all(promises); + } + broadcastMessage({ enabledRulesets: rulesetConfig.enabledRulesets }); +} + +/******************************************************************************/ + +async function setDeveloperMode(state) { rulesetConfig.developerMode = state === true; toggleDeveloperMode(rulesetConfig.developerMode); broadcastMessage({ developerMode: rulesetConfig.developerMode }); - return Promise.all([ - updateUserRules(), - saveRulesetConfig(), - ]); + await saveRulesetConfig(); + return rulesetConfig.developerMode; } /******************************************************************************/ -function onMessage(request, sender, callback) { +async function processDeferredTasks() { + if ( deferredTasks.size === 0 ) { return; } + const promises = []; + if ( deferredTasks.has('registerContentScripts') ) { + promises.push(registerContentScripts()); + } + if ( deferredTasks.has('registerUserScripts') ) { + promises.push(registerUserScripts()); + } + if ( deferredTasks.has('updateUserRules') ) { + promises.push(updateUserRules()); + } + deferredTasks.clear(); + if ( promises.length === 0 ) { return; } + return Promise.all(promises); +} + +/******************************************************************************/ + +async function onMessage(request, sender) { const tabId = sender?.tab?.id ?? false; const frameId = tabId && (sender?.frameId ?? false); - // Does not require trusted origin. + // Does not require extension to be fully initialized + + // Does not require a trusted origin. switch ( request.what ) { case 'insertCSS': if ( frameId === false ) { return false; } // https://bugs.webkit.org/show_bug.cgi?id=262491 - if ( frameId !== 0 && webextFlavor === 'safari' ) { return false; } - browser.scripting.insertCSS({ + if ( frameId !== 0 && webextFlavor === 'safari' ) { return; } + return browser.scripting.insertCSS({ css: request.css, origin: 'USER', target: { tabId, frameIds: [ frameId ] }, }).catch(reason => { ubolErr(`insertCSS/${reason}`); }); - return false; case 'removeCSS': if ( frameId === false ) { return false; } // https://bugs.webkit.org/show_bug.cgi?id=262491 - if ( frameId !== 0 && webextFlavor === 'safari' ) { return false; } - browser.scripting.removeCSS({ + if ( frameId !== 0 && webextFlavor === 'safari' ) { return; } + return browser.scripting.removeCSS({ css: request.css, origin: 'USER', target: { tabId, frameIds: [ frameId ] }, }).catch(reason => { ubolErr(`removeCSS/${reason}`); }); - return false; + + case 'injectCSSProceduralAPI': + return browser.scripting.executeScript({ + files: [ '/js/scripting/css-procedural-api.js' ], + target: { tabId, frameIds: [ frameId ] }, + injectImmediately: true, + }).catch(reason => { + ubolErr(`executeScript/${reason}`); + }); + + default: + break; + } + + // Requires extension to be fully initialized + + await isFullyInitialized; + + // Does not require a trusted origin. + + switch ( request.what ) { case 'toggleToolbarIcon': { if ( tabId ) { toggleToolbarIcon(tabId); } - return false; + return; } case 'startCustomFilters': - if ( frameId === false ) { return false; } - startCustomFilters(tabId, frameId).then(( ) => { - callback(); - }); - return true; + if ( frameId === false ) { return; } + return startCustomFilters(tabId, frameId); case 'terminateCustomFilters': - if ( frameId === false ) { return false; } - terminateCustomFilters(tabId, frameId).then(( ) => { - callback(); - }); - return true; + if ( frameId === false ) { return; } + return terminateCustomFilters(tabId, frameId); case 'injectCustomFilters': - if ( frameId === false ) { return false; } - injectCustomFilters(tabId, frameId, request.hostname).then(selectors => { - callback(selectors); - }); - return true; - - case 'injectCSSProceduralAPI': - browser.scripting.executeScript({ - files: [ '/js/scripting/css-procedural-api.js' ], - target: { tabId, frameIds: [ frameId ] }, - injectImmediately: true, - }).catch(reason => { - ubolErr(`executeScript/${reason}`); - }).then(( ) => { - callback(); - }); - return true; + if ( frameId === false ) { return; } + return injectCustomFilters(tabId, frameId, request.hostname); default: break; } - // Does require trusted origin. + // Requires a trusted origin. // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/MessageSender // Firefox API does not set `sender.origin` - if ( sender.origin !== undefined ) { - if ( sender.origin.toLowerCase() !== UBOL_ORIGIN ) { return; } - } + const isTrustedOrigin = sender?.origin === undefined || + sender.origin.toLowerCase() === UBOL_ORIGIN; + if ( isTrustedOrigin === false ) { return; } switch ( request.what ) { case 'applyRulesets': { - enableRulesets(request.enabledRulesets).then(result => { - if ( result === undefined || result.error ) { - callback(result); - return; - } - rulesetConfig.enabledRulesets = result.enabledRulesets; - return saveRulesetConfig().then(( ) => { - return registerInjectables(); - }).then(( ) => { - callback(result); - }); - }).finally(( ) => { - broadcastMessage({ enabledRulesets: rulesetConfig.enabledRulesets }); - }); - return true; + await applyRulesets(request.enabledRulesets); + if ( request.toRemove ) { + await removeImportedLists(request.toRemove); + } + return; } - case 'getDefaultConfig': - getDefaultRulesetsFromEnv().then(rulesets => { - callback({ - autoReload: defaultConfig.autoReload, - developerMode: defaultConfig.developerMode, - showBlockedCount: defaultConfig.showBlockedCount, - strictBlockMode: defaultConfig.strictBlockMode, - rulesets, - filteringModes: Object.assign(defaultFilteringModes), - }); - }); - return true; + case 'getDefaultConfig': { + const rulesets = await getDefaultRulesetsFromEnv(); + return { + autoReload: defaultConfig.autoReload, + developerMode: defaultConfig.developerMode, + showBlockedCount: defaultConfig.showBlockedCount, + strictBlockMode: defaultConfig.strictBlockMode, + popupBlockMode: defaultConfig.popupBlockMode, + rulesets, + filteringModes: Object.assign(defaultFilteringModes), + }; + } - case 'getOptionsPageData': - Promise.all([ + case 'getCurrentConfig': + return rulesetConfig; + + case 'getOptionsPageData': { + const [ + hasOmnipotence, + defaultFilteringMode, + rulesetDetails, + enabledRulesets, + adminRulesets, + disabledFeatures, + ] = await Promise.all([ hasBroadHostPermissions(), getDefaultFilteringMode(), getRulesetDetails(), - dnr.getEnabledRulesets(), + getEnabledRulesets(), getAdminRulesets(), adminReadEx('disabledFeatures'), - ]).then(results => { - const [ - hasOmnipotence, - defaultFilteringMode, - rulesetDetails, - enabledRulesets, - adminRulesets, - disabledFeatures, - ] = results; - callback({ - hasOmnipotence, - defaultFilteringMode, - enabledRulesets, - adminRulesets, - maxNumberOfEnabledRulesets: dnr.MAX_NUMBER_OF_ENABLED_STATIC_RULESETS, - rulesetDetails: Array.from(rulesetDetails.values()), - autoReload: rulesetConfig.autoReload, - showBlockedCount: rulesetConfig.showBlockedCount, - canShowBlockedCount, - strictBlockMode: rulesetConfig.strictBlockMode, - firstRun: process.firstRun, - isSideloaded, - developerMode: rulesetConfig.developerMode, - disabledFeatures, - }); - process.firstRun = false; - }); - return true; + ]); + process.firstRun = false; + return { + hasOmnipotence, + defaultFilteringMode, + enabledRulesets, + adminRulesets, + maxNumberOfEnabledRulesets: dnr.MAX_NUMBER_OF_ENABLED_STATIC_RULESETS, + rulesetDetails: Array.from(rulesetDetails.values()), + autoReload: rulesetConfig.autoReload, + showBlockedCount: rulesetConfig.showBlockedCount, + canShowBlockedCount, + strictBlockMode: rulesetConfig.strictBlockMode, + popupBlockMode: rulesetConfig.popupBlockMode, + firstRun: process.firstRun, + isSideloaded, + developerMode: rulesetConfig.developerMode, + disabledFeatures, + supportsCompiledFilters: supportsOffscreenDocument, + supportsUserScripts: supportsUserScripts(), + }; + } case 'getEnabledRulesets': - dnr.getEnabledRulesets().then(rulesets => { - callback(rulesets); - }); - return true; + return getEnabledRulesets(); - case 'getRulesetDetails': - getRulesetDetails().then(rulesetDetails => { - callback(Array.from(rulesetDetails.values())); - }); - return true; + case 'getRulesetDetails': { + const rulesetDetails = await getRulesetDetails(); + return Array.from(rulesetDetails.values()); + } case 'getEnabledRulesetsDetails': - getEnabledRulesetsDetails().then(rulesetDetails => { - callback(rulesetDetails); - }); - return true; + return getEnabledRulesetsDetails(); + + case 'getRulesetRules': + return getRulesetRules(request.id); case 'hasBroadHostPermissions': - hasBroadHostPermissions().then(result => { - callback(result); - }); - return true; + return hasBroadHostPermissions(); case 'setAutoReload': rulesetConfig.autoReload = request.state && true || false; - saveRulesetConfig().then(( ) => { - callback(); - broadcastMessage({ autoReload: rulesetConfig.autoReload }); - }); - return true; - - case 'getShowBlockedCount': - callback(rulesetConfig.showBlockedCount); - break; + await saveRulesetConfig(); + broadcastMessage({ autoReload: rulesetConfig.autoReload }); + return; case 'setShowBlockedCount': rulesetConfig.showBlockedCount = request.state && true || false; @@ -421,225 +470,240 @@ function onMessage(request, sender, callback) { displayActionCountAsBadgeText: rulesetConfig.showBlockedCount, }); } - saveRulesetConfig().then(( ) => { - callback(); - broadcastMessage({ showBlockedCount: rulesetConfig.showBlockedCount }); - }); - return true; + await saveRulesetConfig(); + broadcastMessage({ showBlockedCount: rulesetConfig.showBlockedCount }); + return; case 'setStrictBlockMode': - setStrictBlockMode(request.state).then(( ) => { - callback(); - broadcastMessage({ strictBlockMode: rulesetConfig.strictBlockMode }); - }); - return true; + await setStrictBlockMode(request.state); + broadcastMessage({ strictBlockMode: rulesetConfig.strictBlockMode }); + return; + + case 'setPopupBlockMode': + await setPopupBlockMode(request.state); + await registerContentScripts(); + broadcastMessage({ popupBlockMode: rulesetConfig.popupBlockMode }); + return; case 'setDeveloperMode': - setDeveloperMode(request.state).then(( ) => { - callback(); - }); - return true; + return setDeveloperMode(request.state); case 'popupPanelData': { - Promise.all([ + const results = await Promise.all([ hasBroadHostPermissions(), getFilteringMode(request.hostname), adminReadEx('disabledFeatures'), hasCustomFilters(request.hostname), - ]).then(results => { - callback({ - hasOmnipotence: results[0], - level: results[1], - autoReload: rulesetConfig.autoReload, - isSideloaded, - developerMode: rulesetConfig.developerMode, - disabledFeatures: results[2], - hasCustomFilters: results[3], - }); - }); - return true; + ]); + return { + hasOmnipotence: results[0], + level: results[1], + autoReload: rulesetConfig.autoReload, + isSideloaded, + developerMode: rulesetConfig.developerMode, + disabledFeatures: results[2], + hasCustomFilters: results[3], + }; } case 'getFilteringMode': { - getFilteringMode(request.hostname).then(actualLevel => { - callback(actualLevel); - }); - return true; + return getFilteringMode(request.hostname); } case 'gotoURL': - gotoURL(request.url, request.type); - break; + return gotoURL(request.url, request.type); case 'setFilteringMode': { - getFilteringMode(request.hostname).then(beforeLevel => { - if ( request.level === beforeLevel ) { return beforeLevel; } - return setFilteringMode(request.hostname, request.level); - }).then(afterLevel => { - registerInjectables(); - callback(afterLevel); - }); - return true; + const beforeLevel = await getFilteringMode(request.hostname); + if ( request.level === beforeLevel ) { return beforeLevel; } + const afterLevel = await setFilteringMode(request.hostname, request.level); + await Promise.all([ registerContentScripts(), registerUserScripts() ]); + return afterLevel; } case 'setPendingFilteringMode': pendingPermissionRequest = request; - break; + return; case 'getDefaultFilteringMode': { - getDefaultFilteringMode().then(level => { - callback(level); - }); - return true; + return getDefaultFilteringMode(); } - case 'setDefaultFilteringMode': - getDefaultFilteringMode().then(beforeLevel => - setDefaultFilteringMode(request.level).then(afterLevel => - ({ beforeLevel, afterLevel }) - ) - ).then(({ beforeLevel, afterLevel }) => { - if ( afterLevel !== beforeLevel ) { - registerInjectables(); - } - callback(afterLevel); - }); - return true; + case 'setDefaultFilteringMode': { + const beforeLevel = await getDefaultFilteringMode(); + const afterLevel = await setDefaultFilteringMode(request.level); + if ( afterLevel !== beforeLevel ) { + await Promise.all([ registerContentScripts(), registerUserScripts() ]); + } + return afterLevel; + } case 'getFilteringModeDetails': - getFilteringModeDetails(true).then(details => { - callback(details); - }); - return true; - - case 'setFilteringModeDetails': - setFilteringModeDetails(request.modes).then(( ) => { - registerInjectables(); - getDefaultFilteringMode().then(defaultFilteringMode => { - broadcastMessage({ defaultFilteringMode }); - }); - getFilteringModeDetails(true).then(details => { - callback(details); - }); - }); - return true; - - case 'excludeFromStrictBlock': { - excludeFromStrictBlock(request.hostname, request.permanent).then(( ) => { - callback(); - }); - return true; + return getFilteringModeDetails(true); + + case 'setFilteringModeDetails': { + await setFilteringModeDetails(request.modes); + await Promise.all([ registerContentScripts(), registerUserScripts() ]); + const defaultFilteringMode = await getDefaultFilteringMode(); + broadcastMessage({ defaultFilteringMode }); + return getFilteringModeDetails(true); } + case 'excludeFromStrictBlock': + return excludeFromStrictBlock(request.hostname, request.permanent); + case 'getMatchedRules': - getMatchedRules(request.tabId).then(entries => { - callback(entries); - }); - return true; + return getMatchedRules(request.tabId); case 'showMatchedRules': browser.windows.create({ type: 'popup', url: `/matched-rules.html?tab=${request.tabId}`, }); - break; + return; - case 'getEffectiveDynamicRules': - getEffectiveDynamicRules().then(result => { - callback(result); - }); - return true; + case 'getAllDynamicRules': + return dnr.getDynamicRules(); - case 'getEffectiveSessionRules': - getEffectiveSessionRules().then(result => { - callback(result); - }); - return true; + case 'getAllSessionRules': + return dnr.getSessionRules(); case 'getEffectiveUserRules': - getEffectiveUserRules().then(result => { - callback(result); - }); - return true; + return getEffectiveUserRules(); case 'updateUserDnrRules': - updateUserRules().then(result => { - callback(result); - }); - return true; + return updateUserRules(); - case 'addCustomFilters': - addCustomFilters(request.hostname, request.selectors).then(modified => { - if ( modified !== true ) { return; } - return registerInjectables(); - }).then(( ) => { - callback(); - }) - return true; + case 'getAllCustomFilters': + return getAllCustomFilters(); + + case 'addCustomFilters': { + const modified = await addCustomFilters(request.hostname, request.selectors); + if ( modified !== true ) { return; } + const hasScriptletFilters = request.selectors.some(a => isScriptlet(a)); + const hasPlainFilters = request.selectors.some(a => isScriptlet(a) === false); + const promises = []; + if ( hasPlainFilters ) { + promises.push(registerContentScripts()); + } + if ( hasScriptletFilters ) { + promises.push( + updateCompiledFilters().then(( ) => registerUserScripts()) + ); + } + await Promise.all(promises); + return; + } case 'addManyCustomFilters': { const promises = []; + let hasScriptletFilters = false; + let hasPlainFilters = false; for ( const [ hostname, selectors ] of request.entries ) { if ( typeof hostname !== 'string' ) { continue; } if ( hostname === '' ) { continue; } if ( Array.isArray(selectors) === false ) { continue; } if ( selectors.length === 0 ) { continue; } + hasScriptletFilters ||= selectors.some(a => isScriptlet(a)); + hasPlainFilters ||= selectors.some(a => isScriptlet(a) === false); promises.push(addCustomFilters(hostname, selectors)); } - Promise.all(promises).then(results => { - if ( results.some(a => a) === false ) { return; } - return registerInjectables(); - }).then(( ) => { - callback(); - }); - return true; + const results = await Promise.all(promises); + if ( results.some(a => a) === false ) { return; } + promises.length = 0; + if ( hasPlainFilters ) { + promises.push(registerContentScripts()); + } + if ( hasScriptletFilters ) { + promises.push( + updateCompiledFilters().then(( ) => registerUserScripts()) + ); + } + await Promise.all(promises); + return; } - case 'removeCustomFilters': - removeCustomFilters(request.hostname, request.selectors).then(modified => { - if ( modified !== true ) { return; } - return registerInjectables(); - }).then(( ) => { - callback(); - }); - return true; + case 'removeCustomFilters': { + const { selectors } = request; + const modified = await removeCustomFilters(request.hostname, selectors); + if ( modified !== true ) { return; } + const hasScriptletFilters = selectors.some(a => isScriptlet(a)); + const hasPlainFilters = selectors.some(a => isScriptlet(a) === false); + const promises = []; + if ( hasPlainFilters ) { + promises.push(registerContentScripts()); + } + if ( hasScriptletFilters ) { + promises.push( + updateCompiledFilters().then(( ) => registerUserScripts()) + ); + } + await Promise.all(promises); + return; + } - case 'removeAllCustomFilters': - removeAllCustomFilters(request.hostname).then(modified => { - if ( modified !== true ) { return; } - return registerInjectables(); - }).then(( ) => { - callback(); - }); - return true; + case 'removeAllCustomFilters': { + const modified = await removeAllCustomFilters(request.hostname); + if ( modified !== true ) { return; } + await Promise.all([ + registerContentScripts(), + updateCompiledFilters().then(( ) => registerUserScripts()), + ]); + return; + } - case 'customFiltersFromHostname': - customFiltersFromHostname(request.hostname).then(selectors => { - callback(selectors); - }); - return true; + case 'getSandboxFilters': + return getSandboxFilters(); - case 'getAllCustomFilters': - getAllCustomFilters().then(data => { - callback(data); - }); - return true; + case 'setSandboxFilters': { + await setSandboxFilters(request.text); + await updateCompiledFilters(); + await Promise.all([ registerUserScripts(), updateUserRules() ]); + return; + } + + case 'customFiltersFromHostname': + return customFiltersFromHostname(request.hostname); case 'getRegisteredContentScripts': - scrmgr.getRegisteredContentScripts().then(ids => { - callback(ids); - }); - return true; + return getRegisteredContentScripts(); case 'getConsoleOutput': - callback(getConsoleOutput()); - break; + return getConsoleOutput(); + + case 'importFilterList': { + const modified = await addImportedLists([ request.url ]); + if ( modified !== true ) { break; } + const rulesets = await getEnabledRulesets(); + rulesets.push(request.url); + await applyRulesets(rulesets); + return; + } + + case 'getImportedLists': { + return getImportedLists(); + } + + case 'updateImportedLists': { + const count = await updateImportedLists(); + if ( count === 0 ) { break; } + await updateCompiledFilters(); + await Promise.all([ registerUserScripts(), updateUserRules() ]); + return; + } + + case 'pruneCSSCache': { + return pruneCSSCache(); + } + + // This is used to ensure we are not suspended while busy fetching filter + // lists from remote servers. + case 'keepAlive': + return; default: break; } - - return false; } /******************************************************************************/ @@ -683,54 +747,61 @@ async function startSession() { // The default rulesets may have changed, find out new ruleset to enable, // obsolete ruleset to remove. if ( isNewVersion ) { - const previousVersion = rulesetConfig.version; ubolLog(`Version change: ${rulesetConfig.version} => ${currentVersion}`); rulesetConfig.version = currentVersion; await patchDefaultRulesets(); saveRulesetConfig(); - // https://github.com/uBlockOrigin/uBOL-home/issues/670 - if ( intFromVersion(previousVersion) <= intFromVersion('2026.423.0000') ) { - const promises = []; - const customFilters = await getAllCustomFilters(); - for ( const [ hostname, selectors ] of customFilters ) { - let modified = false; - for ( let i = 0; i < selectors.length; i++ ) { - const selector = selectors[i]; - if ( selector.startsWith('0') === false ) { continue; } - selectors[i] = selector.slice(1); - modified = true; - } - if ( modified === false ) { continue; } - promises.push( - removeAllCustomFilters(hostname).then(( ) => - addCustomFilters(hostname, selectors) - ) - ); - } - if ( promises.length !== 0 ) { - await Promise.all(promises); - } - } } - const rulesetsUpdated = await enableRulesets(rulesetConfig.enabledRulesets); + const { + stockUpdated, + importedUpdated, + enabledRulesets, + } = await enableRulesets(rulesetConfig.enabledRulesets); + if ( stockUpdated || importedUpdated ) { + rulesetConfig.enabledRulesets = enabledRulesets; + saveRulesetConfig(); + } - // We need to update the regex rules only when ruleset version changes. - if ( rulesetsUpdated === undefined ) { - if ( isNewVersion ) { - updateDynamicRules(); - } else { - updateSessionRules(); - } + // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/declarativeNetRequest#rulesets + // "The set of enabled static rulesets is persisted across sessions but not across extension updates" + // "[Dynamic] rules persist across sessions and extension updates" + // "[Session] rules do not persist across browser sessions" + if ( isNewVersion ) { + updateDynamicAndSessionRules(); + } else { + updateSessionRules(); } // Permissions may have been removed while the extension was disabled const permissionsUpdated = await syncWithBrowserPermissions(); + // Toggling "user scripts" permission doesn't cause a permissions change + // event. + const userScriptsChanged = supportsUserScripts() !== rulesetConfig.userScripts; + if ( userScriptsChanged ) { + rulesetConfig.userScripts = !rulesetConfig.userScripts; + saveRulesetConfig(); + } + + // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/RegisteredContentScript#persistacrosssessions + // "When an extension updates, content scripts are cleared" + // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/userScripts#extension_updates + // "User scripts are cleared when an extension updates" const shouldInject = isNewVersion || permissionsUpdated || isSideloaded && rulesetConfig.developerMode; - if ( shouldInject ) { - await registerInjectables(); + if ( shouldInject || stockUpdated ) { + deferredTasks.add('registerContentScripts'); + } + if ( importedUpdated ) { + await updateCompiledFilters(); + deferredTasks.add('registerUserScripts'); + deferredTasks.add('updateUserRules'); + } else if ( shouldInject ) { + deferredTasks.add('registerUserScripts'); + deferredTasks.add('updateUserRules'); + } else if ( userScriptsChanged ) { + deferredTasks.add('registerUserScripts'); } // Cosmetic filtering-related content scripts cache fitlering data in @@ -752,12 +823,14 @@ async function startSession() { if ( enableOptimal === false ) { const afterLevel = await setDefaultFilteringMode(MODE_BASIC); if ( afterLevel === MODE_BASIC ) { - registerInjectables(); + deferredTasks.add('registerContentScripts'); process.firstRun = false; } } } + await processDeferredTasks(); + // Required to ensure up to date properties are available when needed adminReadEx('disabledFeatures').then(items => { if ( Array.isArray(items) === false ) { return; } @@ -776,13 +849,11 @@ async function start() { if ( process.wakeupRun === false ) { await startSession(); - } else { - scrmgr.onWakeupRun(); } - const scripts = await scrmgr.getRegisteredContentScripts(); + const scripts = await getRegisteredContentScripts(); if ( scripts.length === 0 ) { - registerInjectables(); + await registerContentScripts(); } toggleDeveloperMode(rulesetConfig.developerMode); @@ -812,13 +883,19 @@ const isFullyInitialized = start().then(( ) => { }); runtime.onMessage.addListener((request, sender, callback) => { - isFullyInitialized.then(( ) => { - const r = onMessage(request, sender, callback); - if ( r !== true ) { callback(); } - }); + if ( request.what.includes(':') ) { return; } + onMessage(request, sender).then(callback); return true; }); +if ( supportsUserScripts() && runtime.onUserScriptMessage ) { + browser.userScripts.configureWorld({ messaging: true }); + runtime.onUserScriptMessage.addListener((request, sender, callback) => { + onMessage(request, sender).then(callback); + return true; + }); +} + browser.permissions.onRemoved.addListener((...args) => { isFullyInitialized.then(( ) => { onPermissionsChanged('removed', ...args); @@ -836,3 +913,14 @@ browser.commands.onCommand.addListener((...args) => { onCommand(...args); }); }); + +browser.alarms.onAlarm.addListener(alarm => { + if ( alarm.name !== 'deferredJobs' ) { return; } + isFullyInitialized.then(( ) => { + if ( process.wakeupRun === false && process.firstAlarm !== true ) { + process.firstAlarm = true; + return resetJobsAlarm(); + } + processDueJobs(onMessage); + }); +}); diff --git a/platform/mv3/extension/js/backup-restore.js b/platform/mv3/extension/js/backup-restore.js index b1ead331f522d..5c5c0d35d56af 100644 --- a/platform/mv3/extension/js/backup-restore.js +++ b/platform/mv3/extension/js/backup-restore.js @@ -19,6 +19,12 @@ Home: https://github.com/gorhill/uBlock */ +import { + addImportedLists, + getImportedLists, + removeImportedLists, +} from './imported-lists.js'; + import { localRead, localRemove, localWrite, runtime, @@ -31,13 +37,22 @@ export async function backupToObject(currentConfig) { const out = {}; const manifest = runtime.getManifest(); out.version = manifest.versionName ?? manifest.version; - const defaultConfig = await sendMessage({ what: 'getDefaultConfig' }); + const [ + defaultConfig, + sandboxFilters, + ] = await Promise.all([ + sendMessage({ what: 'getDefaultConfig' }), + sendMessage({ what: 'getSandboxFilters' }).then(a => a?.trim() ?? ''), + ]); if ( currentConfig.autoReload !== defaultConfig.autoReload ) { out.autoReload = currentConfig.autoReload; } if ( currentConfig.developerMode !== defaultConfig.developerMode ) { out.developerMode = currentConfig.developerMode; } + if ( currentConfig.popupBlockMode !== defaultConfig.popupBlockMode ) { + out.popupBlockMode = currentConfig.popupBlockMode; + } if ( currentConfig.showBlockedCount !== defaultConfig.showBlockedCount ) { out.showBlockedCount = currentConfig.showBlockedCount; } @@ -62,6 +77,9 @@ export async function backupToObject(currentConfig) { if ( customFilters.length !== 0 ) { out.customFilters = customFilters; } + if ( sandboxFilters !== '' ) { + out.sandboxFilters = sandboxFilters.split('\n'); + } const dnrRules = await localRead('userDnrRules'); if ( typeof dnrRules === 'string' && dnrRules.length !== 0 ) { out.dnrRules = dnrRules.split(/\n+/); @@ -94,15 +112,38 @@ export async function restoreFromObject(targetConfig) { state: targetConfig.strictBlockMode ?? defaultConfig.strictBlockMode }); - const enabledRulesets = new Set(defaultConfig.rulesets); + await sendMessage({ + what: 'setPopupBlockMode', + state: targetConfig.popupBlockMode ?? defaultConfig.popupBlockMode + }); + + const enabledRulesets = defaultConfig.rulesets; for ( const entry of targetConfig.rulesets || [] ) { const id = entry.slice(1); if ( entry.startsWith('+') ) { - enabledRulesets.add(id); + if ( enabledRulesets.includes(id) ) { continue; } + enabledRulesets.push(id); } else if ( entry.startsWith('-') ) { - enabledRulesets.delete(id); + const i = enabledRulesets.indexOf(id); + if ( i === -1 ) { continue; } + enabledRulesets.splice(i, 1); } } + const importedLists = await getImportedLists(); + const importedListIds = importedLists.map(a => a.id); + const reImport = /^[a-z-]+:\/\//; + const importedListsToAdd = enabledRulesets.filter(a => + reImport.test(a) && importedListIds.includes(a) === false + ); + const importedListsToRemove = importedListIds.filter(a => + enabledRulesets.includes(a) === false + ); + if ( importedListsToRemove.length ) { + await removeImportedLists(importedListsToRemove); + } + if ( importedListsToAdd.length ) { + await addImportedLists(importedListsToAdd); + } await sendMessage({ what: 'applyRulesets', enabledRulesets: Array.from(enabledRulesets), @@ -143,6 +184,11 @@ export async function restoreFromObject(targetConfig) { }); } + await sendMessage({ + what: 'setSandboxFilters', + text: targetConfig.sandboxFilters?.join('\n') ?? '', + }); + const dnrRules = targetConfig.dnrRules ?? []; if ( dnrRules.length !== 0 ) { await localWrite('userDnrRules', dnrRules.join('\n')); diff --git a/platform/mv3/extension/js/compiled-filters.js b/platform/mv3/extension/js/compiled-filters.js new file mode 100644 index 0000000000000..7bc606b137a97 --- /dev/null +++ b/platform/mv3/extension/js/compiled-filters.js @@ -0,0 +1,315 @@ +/******************************************************************************* + + uBlock Origin Lite - a comprehensive, MV3-compliant content blocker + Copyright (C) 2026-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock +*/ + +import { + browser, + localRead, + localRemove, + localWrite, + runtime, + supportsUserScripts, +} from './ext.js'; + +import { + closeOffscreenDocument, + createOffscreenDocument, +} from './ext-offscreen.js'; + +import { + getAllCustomFilters, + getSandboxFilters, +} from './filter-manager.js'; + +import { + getEnabledImportedLists, + getImportedListCompiledData, + updateImportedListData, +} from './imported-lists.js'; + +import { + isScriptlet, + matchesFromHostnames, +} from './utils.js'; + +import { dnr } from './ext-compat.js'; +import { getFilteringModeDetails } from './mode-manager.js'; +import { supportsOffscreenDocument } from './ext-offscreen.js'; +import { ubolLog } from './debug.js'; + +/******************************************************************************/ + +async function getUserList() { + const customFilters = await getAllCustomFilters(); + const lines = []; + for ( const [ hostname, selectors ] of customFilters ) { + for ( const selector of selectors ) { + if ( isScriptlet(selector) === false ) { continue; } + lines.push(`${hostname}##${selector}`); + } + } + const sandboxFilters = await getSandboxFilters(); + if ( sandboxFilters ) { + lines.push(sandboxFilters); + } + return lines.join('\n').trim(); +} + +/******************************************************************************/ + +async function parseRawFilters() { + const { + promise: offscreenPromise, + resolve: offscreenResolve, + } = Promise.withResolvers(); + const handler = (request, sender, callback) => { + if ( typeof request !== 'object' ) { return; } + switch ( request?.what ) { + case 'compileFilters:getResourceTypes': + callback(Object.values(dnr.ResourceType)); + break; + case 'compileFilters:getUserList': + getUserList().then(text => { + if ( text ) { ubolLog(`Compiling user filters`); } + callback(text); + }); + return true; + case 'compileFilters:result': + offscreenResolve(request); + break; + case 'compileFilters:getEnabledImportedLists': + getEnabledImportedLists().then(result => { + if ( result?.length ) { ubolLog(`Compiling ${result.length} imported lists`); } + callback(result); + }); + return true; + case 'compileFilters:getImportedListCompiledData': + getImportedListCompiledData(request.listid).then(result => { + if ( result?.serialized ) { ubolLog(`Reusing cached data for ${result.listid}`); } + callback(result); + }); + return true; + case 'compileFilters:updateImportedListData': + updateImportedListData(request.listid, request).then(result => { + if ( result ) { ubolLog(`Updated cached data for ${result.listid}`); } + callback(result); + }); + return true; + default: + break; + } + }; + runtime.onMessage.addListener(handler); + const { + promise: timeoutPromise, + resolve: timeoutResolve, + } = Promise.withResolvers(); + self.setTimeout(timeoutResolve, 60000); + const [ result ] = await Promise.all([ + Promise.race([ offscreenPromise, timeoutPromise ]), + createOffscreenDocument('/js/offscreen/compile-filters.html'), + ]); + runtime.onMessage.removeListener(handler); + await closeOffscreenDocument(); + return result; +} + +/******************************************************************************/ + +function prepareUserScripts(id, none, result) { + const out = []; + const excludeHostnames = none.has('all-urls') === false + ? [ ...none ] + : []; + const excludeMatches = excludeHostnames.length !== 0 + ? matchesFromHostnames(excludeHostnames) + : []; + if ( result?.ISOLATED?.length ) { + for ( const script of result.ISOLATED ) { + const directive = { + id: script.id, + world: 'USER_SCRIPT', + allFrames: true, + js: [ { code: script.code } ], + runAt: 'document_start', + matches: matchesFromHostnames(script.hostnames), + }; + if ( excludeMatches.length !== 0 ) { + directive.excludeMatches = excludeMatches.slice(); + } + out.push(directive); + } + } + if ( result?.MAIN?.length ) { + for ( const script of result.MAIN ) { + const directive = { + id: script.id, + world: 'MAIN', + allFrames: true, + js: [ { code: script.code } ], + runAt: 'document_start', + matches: matchesFromHostnames(script.hostnames), + }; + if ( excludeMatches.length !== 0 ) { + directive.excludeMatches = excludeMatches.slice(); + } + out.push(directive); + } + } + return out; +} + +/******************************************************************************/ + +async function saveRules(id, rules) { + const storageId = `${id}Filters.dnrRules`; + const beforeRules = await localRead(storageId); + const afterRules = rules?.length && rules; + const modified = JSON.stringify(afterRules) !== JSON.stringify(beforeRules); + if ( modified === false ) { return false; } + if ( Array.isArray(afterRules) ) { + await localWrite(storageId, afterRules); + } else { + await localRemove(storageId); + } + return true; +} + +/******************************************************************************/ + +async function saveUserScripts(result = {}) { + return Promise.all([ + localWrite('sandboxFilters.userScripts', { + ISOLATED: result.sandbox?.ISOLATED ?? [], + MAIN: result.sandbox?.MAIN ?? [], + }), + localWrite('importedFilters.userScripts', { + ISOLATED: result.imported?.ISOLATED ?? [], + MAIN: result.imported?.MAIN ?? [], + }), + ]); +} + +async function readUserScripts() { + const [ + sandbox = {}, + imported = {}, + ] = await Promise.all([ + localRead('sandboxFilters.userScripts'), + localRead('importedFilters.userScripts'), + ]); + return { sandbox, imported }; +} + +/******************************************************************************/ + +async function register() { + if ( supportsUserScripts() ) { + try { + const toRemove = await browser.userScripts.getScripts(); + if ( toRemove.length !== 0 ) { + await browser.userScripts.unregister(); + ubolLog(`Unregistered userscript ${toRemove.map(a => a.id).join()}`); + } + } catch { + } + } + + const [ + { none, basic }, + { sandbox, imported }, + ] = await Promise.all([ + getFilteringModeDetails(), + readUserScripts(), + ]); + + const toAdd = []; + const sandboxScripts = await prepareUserScripts('sandbox', + none, + sandbox + ); + if ( sandboxScripts.length ) { + toAdd.push(...sandboxScripts); + } + const importedScripts = await prepareUserScripts('imported', + new Set([ ...none, ...basic ]), + imported + ); + if ( importedScripts.length ) { + toAdd.push(...importedScripts); + } + if ( supportsUserScripts() && toAdd.length ) { + try { + await browser.userScripts.register(toAdd).then(( ) => { + ubolLog(`Registered userscript ${toAdd.map(v => v.id)}`); + }); + } catch { + } + } +} + +/******************************************************************************/ + +async function update() { + const [ + hasUserFilters, + hasImportedLists, + ] = await Promise.all([ + getUserList().then(a => Boolean(a)), + getEnabledImportedLists().then(a => Boolean(a.length)), + ]); + + let result; + if ( hasUserFilters || hasImportedLists ) { + result = await parseRawFilters(); + if ( Boolean(result) === false ) { return; } + } + + await Promise.all([ + saveRules('sandbox', result?.sandbox?.dnrRules), + saveRules('imported', result?.imported?.dnrRules), + saveUserScripts(result), + ]); +} + +/******************************************************************************/ + +// This recompiles all sandbox and imported filters. + +export async function updateCompiledFilters() { + if ( supportsOffscreenDocument !== true ) { return false; } + pendingRegister = pendingRegister.then(( ) => update()); + return pendingRegister; +} + +/******************************************************************************/ + +// This registers previously compiled external filters, according to current +// filtering mode details. + +export async function registerUserScripts() { + if ( supportsOffscreenDocument !== true ) { return false; } + pendingRegister = pendingRegister.then(( ) => register()); + return pendingRegister; +} + +/******************************************************************************/ + +let pendingRegister = Promise.resolve(); diff --git a/platform/mv3/extension/js/config.js b/platform/mv3/extension/js/config.js index 988223a758fb9..48abcd493cb2a 100644 --- a/platform/mv3/extension/js/config.js +++ b/platform/mv3/extension/js/config.js @@ -33,6 +33,7 @@ export const rulesetConfig = { autoReload: true, showBlockedCount: true, strictBlockMode: webextFlavor !== 'safari', + popupBlockMode: true, developerMode: false, hasBroadHostPermissions: true, }; @@ -44,9 +45,11 @@ export const process = { wakeupRun: false, }; +let pendingOpPromise = Promise.resolve(); + /******************************************************************************/ -export async function loadRulesetConfig() { +async function _loadRulesetConfig() { const sessionData = await sessionRead('rulesetConfig'); if ( sessionData ) { Object.assign(rulesetConfig, sessionData); @@ -64,7 +67,19 @@ export async function loadRulesetConfig() { process.firstRun = true; } -export async function saveRulesetConfig() { +async function _saveRulesetConfig() { sessionWrite('rulesetConfig', rulesetConfig); return localWrite('rulesetConfig', rulesetConfig); } + +/******************************************************************************/ + +export function loadRulesetConfig() { + pendingOpPromise = pendingOpPromise.then(_loadRulesetConfig); + return pendingOpPromise; +} + +export function saveRulesetConfig() { + pendingOpPromise = pendingOpPromise.then(_saveRulesetConfig); + return pendingOpPromise; +} diff --git a/platform/mv3/extension/js/deep-compare.js b/platform/mv3/extension/js/deep-compare.js new file mode 100644 index 0000000000000..75aa258858de6 --- /dev/null +++ b/platform/mv3/extension/js/deep-compare.js @@ -0,0 +1,49 @@ +/******************************************************************************* + + uBlock Origin Lite - a comprehensive, MV3-compliant content blocker + Copyright (C) 2022-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock +*/ + +export const deepEquals = (a, b) => { + switch ( typeof a ) { + case 'undefined': + case 'boolean': + case 'number': + case 'string': + return a === b; + } + // case 'object': + if ( typeof b !== 'object' ) { return false; } + if ( a === null || b === null ) { return a === b; } + if ( Array.isArray(a) || Array.isArray(b) ) { + if ( Array.isArray(a) === false || Array.isArray(b) === false ) { return false; } + if ( a.length !== b.length ) { return false; } + for ( let i = 0; i < a.length; i++ ) { + if ( deepEquals(a[i], b[i]) === false ) { return false; } + } + return true; + } + const akeys = Object.keys(a); + const bkeys = Object.keys(b); + if ( akeys.length !== bkeys.length ) { return false; } + for ( const k of akeys ) { + if ( deepEquals(a[k], b[k]) === false ) { return false; } + } + return true; +}; + diff --git a/platform/mv3/scriptlets/css-generichigh.template.css b/platform/mv3/extension/js/deferred-tasks.js similarity index 88% rename from platform/mv3/scriptlets/css-generichigh.template.css rename to platform/mv3/extension/js/deferred-tasks.js index 370bc4c04de6a..2e24ba1481b0f 100644 --- a/platform/mv3/scriptlets/css-generichigh.template.css +++ b/platform/mv3/extension/js/deferred-tasks.js @@ -1,7 +1,7 @@ /******************************************************************************* uBlock Origin Lite - a comprehensive, MV3-compliant content blocker - Copyright (C) 2014-present Raymond Hill + Copyright (C) 2026-present Raymond Hill This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,8 +19,4 @@ Home: https://github.com/gorhill/uBlock */ -/* $rulesetId$ */ - -$selectorList$ { - display: none !important; -} +export const deferredTasks = new Set(); diff --git a/platform/mv3/extension/js/develop.js b/platform/mv3/extension/js/develop.js index ab32e10688dc0..6993b7722edac 100644 --- a/platform/mv3/extension/js/develop.js +++ b/platform/mv3/extension/js/develop.js @@ -52,8 +52,12 @@ class Editor { }), ]); const rulesetDetails = await sendMessage({ what: 'getRulesetDetails' }); + const reImported = /^[a-z-]+:\/\//; const parent = qs$('#editors optgroup'); for ( const details of rulesetDetails ) { + if ( reImported.test(details.id) ) { + if ( details.enabled !== true ) { continue; } + } const option = document.createElement('option'); option.value = `dnr.ro.${details.id}`; option.textContent = details.name; @@ -93,7 +97,9 @@ class Editor { readOnly: this.isReadOnly(), }; viewConfig.panels = [ this.ioPanel, this.summaryPanel, ...this.panels ]; - this.view = self.cm6.createEditorView(viewConfig, qs$('#cm-container')); + this.view = self.cm6.createEditorView(viewConfig, + qs$('section[data-pane="develop"] .cm-container') + ); this.lastSavedText = text; self.cm6.foldAll(this.view); self.cm6.resetUndoRedo(this.view); diff --git a/platform/mv3/extension/js/ext-compat.js b/platform/mv3/extension/js/ext-compat.js index 5391c8962366b..3494b21f691c6 100644 --- a/platform/mv3/extension/js/ext-compat.js +++ b/platform/mv3/extension/js/ext-compat.js @@ -19,7 +19,7 @@ Home: https://github.com/gorhill/uBlock */ -import { deepEquals } from './utils.js'; +import { deepEquals } from './deep-compare.js'; export const webext = self.browser || self.chrome; export const dnr = webext.declarativeNetRequest || {}; diff --git a/platform/mv3/extension/js/ext-offscreen.js b/platform/mv3/extension/js/ext-offscreen.js new file mode 100644 index 0000000000000..7fc89fbd524f0 --- /dev/null +++ b/platform/mv3/extension/js/ext-offscreen.js @@ -0,0 +1,36 @@ +/******************************************************************************* + + uBlock Origin Lite - a comprehensive, MV3-compliant content blocker + Copyright (C) 2026-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock +*/ + +// Chromium supports the offscreen API natively + +export const supportsOffscreenDocument = chrome.offscreen !== undefined; + +export async function createOffscreenDocument(path) { + return chrome.offscreen.createDocument({ + url: path, + reasons: [ 'WORKERS' ], + justification: 'To compile custom & imported filters in a modular way from service worker (service workers do not allow dynamic module import)', + }); +} + +export async function closeOffscreenDocument() { + return chrome.offscreen.closeDocument(); +} diff --git a/platform/mv3/extension/js/ext.js b/platform/mv3/extension/js/ext.js index 2c3f871e53e15..16042eb187720 100644 --- a/platform/mv3/extension/js/ext.js +++ b/platform/mv3/extension/js/ext.js @@ -37,6 +37,14 @@ const notAnObject = a => typeof a !== 'object' || a === null; /******************************************************************************/ +export function supportsUserScripts() { + try { browser.userScripts.getScripts(); } + catch { return false; } + return true; +} + +/******************************************************************************/ + // The extension's service worker can be evicted at any time, so when we // send a message, we try a few more times when the message fails to be sent. diff --git a/platform/mv3/extension/js/filter-editor.js b/platform/mv3/extension/js/filter-editor.js new file mode 100644 index 0000000000000..770078a16f0fc --- /dev/null +++ b/platform/mv3/extension/js/filter-editor.js @@ -0,0 +1,368 @@ +/******************************************************************************* + + uBlock Origin Lite - a comprehensive, MV3-compliant content blocker + Copyright (C) 2026-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock +*/ + +import * as sfp from './static-filtering-parser.js'; +import { dom } from './dom.js'; +import { faIconsInit } from './fa-icons.js'; +import { i18n } from './i18n.js'; + +/******************************************************************************/ + +const streamParser = (( ) => { + const nodeHasError = (mode, node) => { + return mode.astParser.getNodeFlags( + node || mode.currentWalkerNode, sfp.NODE_FLAG_ERROR + ) !== 0; + }; + + const colorFromAstNode = mode => { + if ( mode.astParser.nodeIsEmptyString(mode.currentWalkerNode) ) { return '+'; } + if ( nodeHasError(mode) ) { return 'sfp_error'; } + const nodeType = mode.astParser.getNodeType(mode.currentWalkerNode); + switch ( nodeType ) { + case sfp.NODE_TYPE_WHITESPACE: + return ''; + case sfp.NODE_TYPE_COMMENT: + if ( mode.astWalker.canGoDown() ) { break; } + return 'sfp_comment'; + case sfp.NODE_TYPE_COMMENT_URL: + return 'sfp_comment sfp_link'; + case sfp.NODE_TYPE_IGNORE: + return 'sfp_comment'; + case sfp.NODE_TYPE_PREPARSE_DIRECTIVE: + case sfp.NODE_TYPE_PREPARSE_DIRECTIVE_VALUE: + return 'sfp_directive'; + case sfp.NODE_TYPE_PREPARSE_DIRECTIVE_IF_VALUE: { + return 'sfp_def sfp_strong'; + } + case sfp.NODE_TYPE_EXT_OPTIONS_ANCHOR: + return mode.astParser.getFlags(sfp.AST_FLAG_IS_EXCEPTION) + ? 'sfp_tag sfp_strong' + : 'sfp_def sfp_strong'; + case sfp.NODE_TYPE_EXT_DECORATION: + return 'sfp_def'; + case sfp.NODE_TYPE_EXT_PATTERN_RAW: + if ( mode.astWalker.canGoDown() ) { break; } + return 'sfp_variable'; + case sfp.NODE_TYPE_EXT_PATTERN_COSMETIC: + case sfp.NODE_TYPE_EXT_PATTERN_HTML: + return 'sfp_variable'; + case sfp.NODE_TYPE_EXT_PATTERN_RESPONSEHEADER: + case sfp.NODE_TYPE_EXT_PATTERN_SCRIPTLET: + if ( mode.astWalker.canGoDown() ) { break; } + return 'sfp_variable'; + case sfp.NODE_TYPE_EXT_PATTERN_SCRIPTLET_TOKEN: { + return 'sfp_variable'; + } + case sfp.NODE_TYPE_EXT_PATTERN_SCRIPTLET_ARG: + return 'sfp_variable'; + case sfp.NODE_TYPE_NET_EXCEPTION: + return 'sfp_tag sfp_strong'; + case sfp.NODE_TYPE_NET_PATTERN: + if ( mode.astWalker.canGoDown() ) { break; } + if ( mode.astParser.isRegexPattern() ) { + return 'sfp_variable sfp_notice'; + } + return 'sfp_variable'; + case sfp.NODE_TYPE_NET_PATTERN_PART: + return 'sfp_variable'; + case sfp.NODE_TYPE_NET_PATTERN_PART_SPECIAL: + return 'sfp_keyword sfp_strong'; + case sfp.NODE_TYPE_NET_PATTERN_PART_UNICODE: + return 'sfp_variable sfp_unicode'; + case sfp.NODE_TYPE_NET_PATTERN_LEFT_HNANCHOR: + case sfp.NODE_TYPE_NET_PATTERN_LEFT_ANCHOR: + case sfp.NODE_TYPE_NET_PATTERN_RIGHT_ANCHOR: + case sfp.NODE_TYPE_NET_OPTION_NAME_NOT: + return 'sfp_keyword sfp_strong'; + case sfp.NODE_TYPE_NET_OPTIONS_ANCHOR: + case sfp.NODE_TYPE_NET_OPTION_SEPARATOR: + mode.lastNetOptionType = 0; + return 'sfp_def sfp_strong'; + case sfp.NODE_TYPE_NET_OPTION_NAME_UNKNOWN: + mode.lastNetOptionType = 0; + return 'sfp_error'; + case sfp.NODE_TYPE_NET_OPTION_NAME_1P: + case sfp.NODE_TYPE_NET_OPTION_NAME_STRICT1P: + case sfp.NODE_TYPE_NET_OPTION_NAME_3P: + case sfp.NODE_TYPE_NET_OPTION_NAME_STRICT3P: + case sfp.NODE_TYPE_NET_OPTION_NAME_ALL: + case sfp.NODE_TYPE_NET_OPTION_NAME_BADFILTER: + case sfp.NODE_TYPE_NET_OPTION_NAME_CNAME: + case sfp.NODE_TYPE_NET_OPTION_NAME_CSP: + case sfp.NODE_TYPE_NET_OPTION_NAME_CSS: + case sfp.NODE_TYPE_NET_OPTION_NAME_DENYALLOW: + case sfp.NODE_TYPE_NET_OPTION_NAME_DOC: + case sfp.NODE_TYPE_NET_OPTION_NAME_EHIDE: + case sfp.NODE_TYPE_NET_OPTION_NAME_EMPTY: + case sfp.NODE_TYPE_NET_OPTION_NAME_FONT: + case sfp.NODE_TYPE_NET_OPTION_NAME_FRAME: + case sfp.NODE_TYPE_NET_OPTION_NAME_FROM: + case sfp.NODE_TYPE_NET_OPTION_NAME_GENERICBLOCK: + case sfp.NODE_TYPE_NET_OPTION_NAME_GHIDE: + case sfp.NODE_TYPE_NET_OPTION_NAME_IMAGE: + case sfp.NODE_TYPE_NET_OPTION_NAME_IMPORTANT: + case sfp.NODE_TYPE_NET_OPTION_NAME_INLINEFONT: + case sfp.NODE_TYPE_NET_OPTION_NAME_INLINESCRIPT: + case sfp.NODE_TYPE_NET_OPTION_NAME_MATCHCASE: + case sfp.NODE_TYPE_NET_OPTION_NAME_MEDIA: + case sfp.NODE_TYPE_NET_OPTION_NAME_METHOD: + case sfp.NODE_TYPE_NET_OPTION_NAME_MP4: + case sfp.NODE_TYPE_NET_OPTION_NAME_NOOP: + case sfp.NODE_TYPE_NET_OPTION_NAME_OBJECT: + case sfp.NODE_TYPE_NET_OPTION_NAME_OTHER: + case sfp.NODE_TYPE_NET_OPTION_NAME_PING: + case sfp.NODE_TYPE_NET_OPTION_NAME_POPUNDER: + case sfp.NODE_TYPE_NET_OPTION_NAME_POPUP: + case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT: + case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE: + case sfp.NODE_TYPE_NET_OPTION_NAME_REMOVEPARAM: + case sfp.NODE_TYPE_NET_OPTION_NAME_RESPONSEHEADER: + case sfp.NODE_TYPE_NET_OPTION_NAME_REQUESTHEADER: + case sfp.NODE_TYPE_NET_OPTION_NAME_SCRIPT: + case sfp.NODE_TYPE_NET_OPTION_NAME_SHIDE: + case sfp.NODE_TYPE_NET_OPTION_NAME_TO: + case sfp.NODE_TYPE_NET_OPTION_NAME_TOP: + case sfp.NODE_TYPE_NET_OPTION_NAME_URLTRANSFORM: + case sfp.NODE_TYPE_NET_OPTION_NAME_XHR: + case sfp.NODE_TYPE_NET_OPTION_NAME_WEBRTC: + case sfp.NODE_TYPE_NET_OPTION_NAME_WEBSOCKET: + mode.lastNetOptionType = nodeType; + return 'sfp_def'; + case sfp.NODE_TYPE_NET_OPTION_ASSIGN: + case sfp.NODE_TYPE_NET_OPTION_QUOTE: + return 'sfp_def'; + case sfp.NODE_TYPE_NET_OPTION_VALUE: + if ( mode.astWalker.canGoDown() ) { break; } + switch ( mode.lastNetOptionType ) { + case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT: + case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE: + return 'sfp_value'; + default: + break; + } + return 'sfp_value'; + case sfp.NODE_TYPE_OPTION_VALUE_NOT: + return 'sfp_keyword sfp_strong'; + case sfp.NODE_TYPE_OPTION_VALUE_DOMAIN: + return 'sfp_value'; + case sfp.NODE_TYPE_OPTION_VALUE_SEPARATOR: + return 'sfp_def'; + default: + break; + } + return '+'; + }; + + class ModeState { + constructor() { + this.astParser = new sfp.AstFilterParser({ + interactive: true, + localSource: true, + nativeCssHas: true, + trustedSource: true, + }); + this.astWalker = this.astParser.getWalker(); + this.currentWalkerNode = 0; + this.lastNetOptionType = 0; + } + } + + return { + languageData: { + commentTokens: { line: '!' }, + }, + tokenTable: [ + 'sfp_comment', + 'sfp_def', + 'sfp_directive', + 'sfp_error', + 'sfp_ext-dom', + 'sfp_ext-html', + 'sfp_ext-js', + 'sfp_keyword', + 'sfp_link', + 'sfp_net', + 'sfp_notice', + 'sfp_strong', + 'sfp_tag', + 'sfp_unicode', + 'sfp_value', + 'sfp_variable', + ], + startState() { + return new ModeState(); + }, + copyState(other) { + return other; + }, + token(stream, state) { + if ( stream.sol() ) { + state.astParser.parse(stream.string); + if ( state.astParser.getFlags(sfp.AST_FLAG_UNSUPPORTED) !== 0 ) { + stream.skipToEnd(); + return 'sfp_error'; + } + if ( state.astParser.getType() === sfp.AST_TYPE_NONE ) { + stream.skipToEnd(); + return 'sfp_comment'; + } + state.currentWalkerNode = state.astWalker.reset(); + } else if ( nodeHasError(state) ) { + state.currentWalkerNode = state.astWalker.right(); + } else { + state.currentWalkerNode = state.astWalker.next(); + } + let style = ''; + while ( state.currentWalkerNode !== 0 ) { + style = colorFromAstNode(state, stream); + if ( style !== '+' ) { break; } + state.currentWalkerNode = state.astWalker.next(); + } + if ( style === '+' ) { + stream.skipToEnd(); + return null; + } + stream.pos = state.astParser.getNodeStringEnd(state.currentWalkerNode); + if ( state.astParser.isNetworkFilter() ) { + return style ? `sfp_net ${style}` : 'sfp_net'; + } + if ( state.astParser.isExtendedFilter() ) { + let flavor = ''; + if ( state.astParser.isCosmeticFilter() ) { + flavor = 'sfp_ext-dom'; + } else if ( state.astParser.isScriptletFilter() ) { + flavor = 'sfp_ext-js'; + } else if ( state.astParser.isHtmlFilter() ) { + flavor = 'sfp_ext-html'; + } + if ( flavor !== '' ) { + style = `${flavor} ${style}`; + } + } + style = style.trim(); + return style !== '' ? style : null; + }, + }; +})(); + +/******************************************************************************/ + +export class FilterEditor { + constructor(parent, text = '') { + this.ioPanel = self.cm6.createViewPanel(); + const viewConfig = { + text, + oneDark: dom.cl.has(':root', 'dark'), + lineWrapping: true, + updateListener: info => { this.updateListener(info); }, + saveListener: ( ) => { this.saveContent(); }, + lineError: true, + spanError: true, + streamParser, + panels: [ this.ioPanel ], + }; + this.view = self.cm6.createEditorView(viewConfig, parent); + this.lastSavedText = text; + self.cm6.resetUndoRedo(this.view); + this.updateIOPanel(); + } + + getContent() { + return this.normalizeContent(this.view.state.doc.toString()); + } + + setContent(text, saved = false) { + text = this.normalizeContent(text); + if ( saved ) { + this.lastSavedText = text; + } + this.view.dispatch({ + changes: { + from: 0, to: this.view.state.doc.length, + insert: text, + }, + }); + this.view.focus(); + } + + normalizeContent(text) { + text ||= ''; + text = text.trim(); + if ( text !== '' ) { text += '\n'; } + return text; + } + + contentChanged() { + const text = this.normalizeContent(this.getContent()); + return text !== this.lastSavedText; + } + + async loadContent(text) { + this.setContent(text, true); + self.cm6.resetUndoRedo(this.view); + this.updateView(); + } + + async saveContent() { + this.lastSavedText = this.getContent(); + this.updateView(); + } + + revertContent() { + if ( this.contentChanged() === false ) { return; } + this.setContent(this.lastSavedText); + } + + updateListener(info) { + if ( info.docChanged === false ) { return; } + this.updateView(); + } + + + updateView() { + const changed = this.contentChanged(); + dom.attr('#apply', 'disabled', changed ? null : ''); + dom.attr('#revert', 'disabled', changed ? null : ''); + } + + updateIOPanel() { + const ioButtons = [ 'apply', 'revert' ]; + const template = document.querySelector('template.io-panel'); + const fragment = template.content.cloneNode(true); + const root = fragment.querySelector('.io-panel'); + i18n.render(root); + faIconsInit(root); + root.dataset.io = ioButtons.join(' '); + const config = { + dom: root, + mount: ( ) => { + dom.on('#apply', 'click', ( ) => { + this.saveContent(); + }); + dom.on('#revert', 'click', ( ) => { + this.revertContent(); + }); + }, + }; + this.ioPanel.render(this.view, config); + } +} diff --git a/platform/mv3/extension/js/filter-lists.js b/platform/mv3/extension/js/filter-lists.js index 17cc5318a6e2a..58efe7122452f 100644 --- a/platform/mv3/extension/js/filter-lists.js +++ b/platform/mv3/extension/js/filter-lists.js @@ -26,10 +26,10 @@ import { localRead, localWrite, sendMessage } from './ext.js'; /******************************************************************************/ -export const rulesetMap = new Map(); +const rulesetMap = new Map(); +const visuallyEnabledRulesets = new Set(); -let cachedRulesetData = {}; -let hideUnusedSet = new Set([ 'ads', 'regions' ]); +let hideUnusedSet = new Set([ 'ads', 'regions', 'imported' ]); /******************************************************************************/ @@ -43,10 +43,12 @@ function renderTotalRuleCounts() { let rulesetCount = 0; let filterCount = 0; let ruleCount = 0; - for ( const liEntry of qsa$('#lists .listEntry[data-role="leaf"][data-rulesetid]') ) { - if ( qs$(liEntry, 'input[type="checkbox"]:checked') === null ) { continue; } - rulesetCount += 1; - const stats = rulesetStats(liEntry.dataset.rulesetid); + for ( const listEntry of qsa$('#lists .listEntry[data-role="leaf"][data-rulesetid]') ) { + if ( qs$(listEntry, 'input[type="checkbox"]:checked') === null ) { continue; } + if ( listEntry.dataset.imported === undefined ) { + rulesetCount += 1; + } + const stats = rulesetStats(listEntry.dataset.rulesetid); if ( stats === undefined ) { continue; } ruleCount += stats.ruleCount; filterCount += stats.filterCount; @@ -57,7 +59,7 @@ function renderTotalRuleCounts() { ); dom.cl.toggle(dom.body, 'noMoreRuleset', - rulesetCount === cachedRulesetData.maxNumberOfEnabledRulesets + rulesetCount === self.cachedRulesetData.maxNumberOfEnabledRulesets ); } @@ -102,7 +104,7 @@ function rulesetStats(rulesetId) { /******************************************************************************/ function isAdminRuleset(listkey) { - const { adminRulesets = [] } = cachedRulesetData; + const { adminRulesets = [] } = self.cachedRulesetData; for ( const id of adminRulesets ) { const pos = id.indexOf(listkey); if ( pos === 0 ) { return true; } @@ -115,30 +117,54 @@ function isAdminRuleset(listkey) { /******************************************************************************/ -export function renderFilterLists(rulesetData) { - cachedRulesetData = rulesetData; - const { enabledRulesets, rulesetDetails } = cachedRulesetData; +export async function renderFilterLists(incremental = false) { + if ( incremental && renderFilterLists.visible !== true ) { return; } + renderFilterLists.visible = true; + + const [ + enabledRulesets, + rulesetDetails, + ] = await Promise.all([ + sendMessage({ what: 'getEnabledRulesets' }), + sendMessage({ what: 'getRulesetDetails' }), + ]); - const shouldUpdate = rulesetMap.size !== 0; + self.cachedRulesetData.enabledRulesets = enabledRulesets; + self.cachedRulesetData.rulesetDetails = rulesetDetails; - rulesetDetails.forEach(rule => rulesetMap.set(rule.id, rule)); + visuallyEnabledRulesets.clear(); + rulesetMap.clear(); + rulesetDetails.forEach(rule => { + rulesetMap.set(rule.id, rule); + }); const listStatsTemplate = i18n$('perRulesetStats'); + const beforeListEntries = new Set(qsa$('#lists .listEntry:not([data-role="root"])')); const initializeListEntry = (ruleset, listEntry) => { const on = enabledRulesets.includes(ruleset.id); + if ( on ) { + visuallyEnabledRulesets.add(ruleset.id); + } if ( dom.cl.has(listEntry, 'toggled') === false ) { dom.prop(qs$(listEntry, ':scope > .detailbar input'), 'checked', on); } if ( ruleset.homeURL ) { dom.attr(qs$(listEntry, 'a.support'), 'href', ruleset.homeURL); } - dom.cl.toggle(listEntry, 'isDefault', ruleset.enabled === true); + const isImported = ruleset.group === 'imported'; + dom.cl.toggle(listEntry, 'isDefault', + ruleset.enabled === true && isImported === false + ); + if ( isImported ) { + listEntry.dataset.imported = ''; + } const stats = rulesetStats(ruleset.id); if ( stats === undefined ) { return; } listEntry.title = listStatsTemplate .replace('{{ruleCount}}', renderNumber(stats.ruleCount)) .replace('{{filterCount}}', renderNumber(stats.filterCount)); + if ( isImported ) { return; } const fromAdmin = isAdminRuleset(ruleset.id); dom.cl.toggle(listEntry, 'fromAdmin', fromAdmin); dom.attr( @@ -148,31 +174,27 @@ export function renderFilterLists(rulesetData) { ); }; - // Update already rendered DOM lists - if ( shouldUpdate ) { - for ( const listEntry of qsa$('#lists .listEntry[data-rulesetid]') ) { - const rulesetid = listEntry.dataset.rulesetid; - const ruleset = rulesetMap.get(rulesetid); - initializeListEntry(ruleset, listEntry); - } - updateNodes(); - renderTotalRuleCounts(); - return; - } - - const createListEntry = (listDetails, depth) => { + const createListEntry = (entryid, listDetails, depth) => { if ( listDetails.lists === undefined ) { + const listEntry = qs$(`[data-role="leaf"][data-rulesetid="${entryid}"]`); + if ( listEntry !== null ) { return listEntry; } return nodeFromTemplate('listEntryLeaf', '.listEntry'); } if ( depth !== 0 ) { + const listEntry = qs$(`[data-role="node"][data-nodeid="${entryid}"]`); + if ( listEntry !== null ) { return listEntry; } return nodeFromTemplate('listEntryNode', '.listEntry'); } + const listEntry = qs$(`[data-role="rootnode"][data-nodeid="${entryid}"]`); + if ( listEntry !== null ) { return listEntry; } return nodeFromTemplate('listEntryRoot', '.listEntry'); }; const createListEntries = (parentkey, listTree, depth = 0) => { - const listEntries = nodeFromTemplate('listEntries', '.listEntries'); const treeEntries = Object.entries(listTree); + const listEntries = qs$(`#lists .listEntry[data-nodeid="${parentkey}"] > .listEntries`) || + qs$('#lists > .listEntries') || + nodeFromTemplate('listEntries', '.listEntries'); if ( depth !== 0 ) { const reEmojis = /\p{Emoji}+/gu; treeEntries.sort((a ,b) => { @@ -184,31 +206,38 @@ export function renderFilterLists(rulesetData) { return as.localeCompare(bs); }); } - for ( const [ listkey, listDetails ] of treeEntries ) { - const listEntry = createListEntry(listDetails, depth); + for ( const [ listid, listDetails ] of treeEntries ) { + const listEntry = createListEntry(listid, listDetails, depth); + beforeListEntries.delete(listEntry); + const newEntry = listEntry.parentElement === null; if ( listDetails.lists === undefined ) { - listEntry.dataset.rulesetid = listkey; + listEntry.dataset.rulesetid = listid; } else { - listEntry.dataset.nodeid = listkey; - dom.cl.toggle(listEntry, 'hideUnused', hideUnusedSet.has(listkey)); + listEntry.dataset.nodeid = listid; + dom.cl.toggle(listEntry, 'hideUnused', hideUnusedSet.has(listid)); + } + if ( newEntry ) { + qs$(listEntry, ':scope > .detailbar .listname').append( + i18n.patchUnicodeFlags(listDetails.name) + ); } - qs$(listEntry, ':scope > .detailbar .listname').append( - i18n.patchUnicodeFlags(listDetails.name) - ); if ( listDetails.lists !== undefined ) { - listEntry.append(createListEntries(listkey, listDetails.lists, depth+1)); - dom.cl.toggle(listEntry, 'expanded', true/*listIsExpanded(listkey)*/); - //updateListNode(listEntry); + const listEntries = createListEntries(listid, listDetails.lists, depth+1) + if ( listEntries.parentElement === null ) { + listEntry.append(listEntries); + } } else { initializeListEntry(listDetails, listEntry); } - listEntries.append(listEntry); + if ( newEntry ) { + listEntries.append(listEntry); + } } return listEntries; }; // Visually split the filter lists in groups - const groups = new Map([ + const groups = [ [ 'default', rulesetDetails.filter(ruleset => @@ -238,15 +267,20 @@ export function renderFilterLists(rulesetData) { 'misc', rulesetDetails.filter(ruleset => ruleset.group === undefined && - typeof ruleset.lang !== 'string' + typeof ruleset.lang !== 'string' ), ], [ 'regions', rulesetDetails.filter(ruleset => - ruleset.group === 'regions' + ruleset.group === 'regions' + ), + ], [ + 'imported', + rulesetDetails.filter(ruleset => + ruleset.group === 'imported' ), ], - ]); + ]; dom.cl.toggle(dom.body, 'hideUnused', mustHideUnusedLists('*')); @@ -294,11 +328,15 @@ export function renderFilterLists(rulesetData) { promoteLonelySublist(listTree[key]); } const listEntries = createListEntries('root', listTree); + for ( const listEntry of beforeListEntries ) { + listEntry.remove(); + } updateNodes(listEntries); - dom.clear('#lists'); - qs$('#lists').append(listEntries); + if ( listEntries.parentElement === null ) { + qs$('#lists').append(listEntries); + } renderTotalRuleCounts(); } @@ -338,12 +376,6 @@ function toggleHideUnusedLists(which) { localWrite('hideUnusedFilterLists', Array.from(hideUnusedSet)); } -dom.on('#lists', 'click', '.listEntry[data-nodeid] > .detailbar, .listExpander', ev => { - toggleHideUnusedLists( - dom.attr(ev.target.closest('[data-nodeid]'), 'data-nodeid') - ); -}); - // Initialize from saved state. localRead('hideUnusedFilterLists').then(value => { if ( Array.isArray(value) === false ) { return; } @@ -388,32 +420,41 @@ const searchFilterLists = ( ) => { const perListHaystack = new WeakMap(); -dom.on('#findInLists', 'input', searchFilterLists); - /******************************************************************************/ const applyEnabledRulesets = (( ) => { - const apply = async ( ) => { + const apply = async (final = false) => { dom.cl.add(dom.body, 'committing'); const enabledRulesets = []; - for ( const liEntry of qsa$('#lists .listEntry[data-role="leaf"][data-rulesetid]') ) { - const checked = qs$(liEntry, 'input[type="checkbox"]:checked') !== null; + const rulesetEntries = + qsa$('#lists [data-role="leaf"][data-rulesetid]'); + for ( const listEntry of rulesetEntries ) { + const checked = qs$(listEntry, 'input[type="checkbox"]:checked') !== null; if ( checked === false ) { continue; } - const { rulesetid } = liEntry.dataset; - if ( dom.cl.has(liEntry, 'fromAdmin') ) { continue; } + const { rulesetid } = listEntry.dataset; + if ( dom.cl.has(listEntry, 'fromAdmin') ) { continue; } enabledRulesets.push(rulesetid); } dom.cl.remove('#lists .listEntry.toggled', 'toggled'); + const toRemove = Array.from( + qsa$('#lists [data-role="leaf"][data-rulesetid][data-remove]') + ).map(a => a.dataset.rulesetid); + const modified = hashFromIterable(enabledRulesets) !== - hashFromIterable(cachedRulesetData.enabledRulesets); + hashFromIterable(visuallyEnabledRulesets) || + final && toRemove.length; if ( modified ) { - const result = await sendMessage({ + const msg = { what: 'applyRulesets', enabledRulesets, - }); + }; + if ( final ) { + msg.toRemove = toRemove; + } + const result = await sendMessage(msg); dom.text('#dnrError', result?.error || ''); } @@ -426,7 +467,7 @@ const applyEnabledRulesets = (( ) => { if ( timer !== undefined ) { return; } self.clearTimeout(timer); timer = undefined; - apply(); + apply(true); }); return function() { @@ -444,21 +485,81 @@ const applyEnabledRulesets = (( ) => { } })(); -dom.on('#lists', 'change', '.listEntry input[type="checkbox"]', ev => { - const input = ev.target; - const listEntry = input.closest('.listEntry'); - if ( listEntry === null ) { return; } - if ( listEntry.dataset.nodeid !== undefined ) { - const checkAll = input.checked || - dom.cl.has(qs$(listEntry, ':scope > .detailbar .checkbox'), 'partial'); - for ( const subListEntry of qsa$(listEntry, ':scope > .listEntries .listEntry[data-rulesetid]') ) { - dom.cl.add(subListEntry, 'toggled'); - dom.prop(qsa$(subListEntry, ':scope > .detailbar input'), 'checked', checkAll); - } - } else { - dom.cl.add(listEntry, 'toggled'); - } +/******************************************************************************/ + +async function importFromInput() { + const input = qs$('.importRulesetURL input[type="url"]'); + const url = input.value; + if ( /^[a-z-]+:\/\/(?:\S+\/\S*|\/\S+)/m.test(url) === false ) { return; } + dom.cl.add(dom.body, 'committing'); + await sendMessage({ what: 'importFilterList', url }); + qs$('.importRulesetURL').open = false; + input.value = ''; + dom.cl.remove(dom.body, 'committing'); +} + +function removeImportedList(ev) { + const listEntry = ev.target.closest('[data-role="leaf"]'); + dom.cl.add(listEntry, 'toggled'); + const input = qs$(listEntry, 'input[type="checkbox"]'); + listEntry.dataset.remove = JSON.stringify(input.checked); + input.checked = false; + input.setAttribute('disabled', ''); updateNodes(); renderTotalRuleCounts(); applyEnabledRulesets(); -}); +} + +function unremoveImportedList(ev) { + const listEntry = ev.target.closest('[data-role="leaf"]'); + dom.cl.add(listEntry, 'toggled'); + const input = qs$(listEntry, 'input[type="checkbox"]'); + input.removeAttribute('disabled'); + input.checked = JSON.parse(listEntry.dataset.remove); + delete listEntry.dataset.remove; + updateNodes(); + renderTotalRuleCounts(); + applyEnabledRulesets(); +} + +/******************************************************************************/ + +async function start() { + await renderFilterLists(); + + dom.on('#findInLists', 'input', searchFilterLists); + dom.on('#lists', 'click', '.listEntry[data-nodeid] > .detailbar, .listExpander', ev => { + toggleHideUnusedLists( + dom.attr(ev.target.closest('[data-nodeid]'), 'data-nodeid') + ); + }); + dom.on('#lists', 'change', '.listEntry input[type="checkbox"]', ev => { + const input = ev.target; + const listEntry = input.closest('.listEntry'); + if ( listEntry === null ) { return; } + if ( listEntry.dataset.nodeid !== undefined ) { + const checkAll = input.checked || + dom.cl.has(qs$(listEntry, ':scope > .detailbar .checkbox'), 'partial'); + for ( const subListEntry of qsa$(listEntry, ':scope > .listEntries .listEntry[data-rulesetid]') ) { + dom.cl.add(subListEntry, 'toggled'); + dom.prop(qsa$(subListEntry, ':scope > .detailbar input'), 'checked', checkAll); + } + } else { + dom.cl.add(listEntry, 'toggled'); + } + updateNodes(); + renderTotalRuleCounts(); + applyEnabledRulesets(); + }); + dom.on('section[data-pane="rulesets"] button:has([data-i18n="addButton"])', 'click', + ( ) => { importFromInput(); } + ); + dom.on('#lists', 'click', '[data-role="leaf"][data-imported] .doRemove', + removeImportedList + ); + dom.on('#lists', 'click', '[data-role="leaf"][data-imported] .undoRemove', + unremoveImportedList + ); +} + +dom.onFirstShown(start, qs$('section[data-pane="rulesets"]')); diff --git a/platform/mv3/extension/js/filter-manager-ui.js b/platform/mv3/extension/js/filter-manager-ui.js index 8b46012e32178..e0eb861a44da1 100644 --- a/platform/mv3/extension/js/filter-manager-ui.js +++ b/platform/mv3/extension/js/filter-manager-ui.js @@ -96,10 +96,12 @@ async function removeSelectorsFromHostname(node) { qsa$(hostnameNode, 'li.selector.removed:not([data-ugly=""])') ).map(a => a.dataset.ugly); if ( selectors.length === 0 ) { return; } + dom.cl.add(dom.body, 'committing'); updateContentEditability(false); await sendMessage({ what: 'removeCustomFilters', hostname, selectors }); await debounceRenderCustomFilters(); updateContentEditability(true); + dom.cl.remove(dom.body, 'committing'); } async function unremoveSelectorsFromHostname(node) { @@ -109,10 +111,12 @@ async function unremoveSelectorsFromHostname(node) { if ( hostname === undefined ) { return; } const selectors = selectorsFromNode(hostnameNode); if ( selectors.length === 0 ) { return; } + dom.cl.add(dom.body, 'committing'); updateContentEditability(false); await sendMessage({ what: 'addCustomFilters', hostname, selectors }); await debounceRenderCustomFilters(); updateContentEditability(true); + dom.cl.remove(dom.body, 'committing'); } /******************************************************************************/ @@ -281,13 +285,13 @@ async function onHostnameChanged(target, before, after) { return; } + dom.cl.add(dom.body, 'committing'); // Remove old hostname from storage if ( hostnameNode.dataset.ugly ) { await sendMessage({ what: 'removeAllCustomFilters', hostname: hostnameNode.dataset.ugly, }); } - // Add selectors under new hostname to storage hostnameNode.dataset.ugly = uglyAfter; hostnameNode.dataset.pretty = after; @@ -295,8 +299,8 @@ async function onHostnameChanged(target, before, after) { hostname: hostnameFromNode(target), selectors: selectorsFromNode(target), }); - await debounceRenderCustomFilters(); + dom.cl.remove(dom.body, 'committing'); } async function onSelectorChanged(target, before, after) { @@ -312,14 +316,13 @@ async function onSelectorChanged(target, before, after) { return; } + dom.cl.add(dom.body, 'committing'); const hostname = hostnameFromNode(target); - // Remove old selector from storage await sendMessage({ what: 'removeCustomFilters', hostname, selectors: [ selectorNode.dataset.ugly ], }); - // Add new selector to storage selectorNode.dataset.ugly = ugly; selectorNode.dataset.pretty = pretty; @@ -327,8 +330,8 @@ async function onSelectorChanged(target, before, after) { hostname, selectors: [ ugly ], }); - await debounceRenderCustomFilters(); + dom.cl.remove(dom.body, 'committing'); } async function onTextChanged(target) { @@ -587,6 +590,29 @@ function exportToFile() { /******************************************************************************/ +async function startsSandboxEditor() { + if ( startsSandboxEditor.editor ) { return; } + + const { FilterEditor } = await import('./filter-editor.js'); + + const SandboxFilterEditor = class extends FilterEditor { + async saveContent() { + if ( this.contentChanged() === false ) { return; } + await sendMessage({ what: 'setSandboxFilters', text: this.getContent() }); + await super.saveContent(); + } + async loadContent() { + const text = await sendMessage({ what: 'getSandboxFilters' }); + await super.loadContent(text); + } + } + + startsSandboxEditor.editor = new SandboxFilterEditor(qs$('#sandboxEditor .cm-container')); + await startsSandboxEditor.editor.loadContent(); +} + +/******************************************************************************/ + async function start() { renderCustomFilters(); @@ -601,11 +627,16 @@ async function start() { dom.on('section[data-pane="filters"] [data-i18n="exportButton"]', 'click', exportToFile); browser.storage.local.onChanged.addListener((changes, area) => { + if ( dom.cl.has(dom.body, 'committing') ) { return; } if ( area !== undefined && area !== 'local' ) { return; } if ( Object.keys(changes).some(a => a.startsWith('site.')) ) { debounceRenderCustomFilters(); + } else if ( changes.sandboxFilters ) { + startsSandboxEditor.editor.loadContent(); } }); + + dom.onFirstShown(startsSandboxEditor, qs$('section[data-pane="filters"] aside#sandboxEditor')); } /******************************************************************************/ diff --git a/platform/mv3/extension/js/filter-manager.js b/platform/mv3/extension/js/filter-manager.js index 8778acced5f47..0eed1c2783248 100644 --- a/platform/mv3/extension/js/filter-manager.js +++ b/platform/mv3/extension/js/filter-manager.js @@ -25,24 +25,20 @@ import { localRead, localRemove, localWrite, - runtime, } from './ext.js'; import { intersectHostnameIters, + isScriptlet, matchesFromHostnames, subtractHostnameIters, } from './utils.js'; -import { - ubolErr, - ubolLog, -} from './debug.js'; +import { ubolErr } from './debug.js'; /******************************************************************************/ const isProcedural = a => a.startsWith('{'); -const isScriptlet = a => a.startsWith('+js'); const isCSS = a => isProcedural(a) === false && isScriptlet(a) === false; /******************************************************************************/ @@ -204,6 +200,8 @@ export async function registerCustomFilters(context) { id: 'css-user', js: [ '/js/scripting/css-user.js' ], matches: matchesFromHostnames(hostnames), + allFrames: true, + matchOriginAsFallback: true, runAt: 'document_start', }; if ( excludeHostnames.length !== 0 ) { @@ -281,117 +279,13 @@ async function removeCustomFiltersByKey(key, toRemove) { /******************************************************************************/ -export function isUserScriptsAvailable() { - if ( browser.offscreen === undefined ) { return false; } - try { - chrome.userScripts.getScripts(); - } catch { - return false; - } - return true; +export function getSandboxFilters() { + return localRead('sandboxFilters'); } -export async function registerCustomScriptlets(context) { - if ( isUserScriptsAvailable() === false ) { return; } - const { none, basic, optimal, complete } = context.filteringModeDetails; - const notNone = [ ...basic, ...optimal, ...complete ]; - if ( registerCustomScriptlets.promise ) { - registerCustomScriptlets.promise = registerCustomScriptlets.promise.then( - registerCustomScriptlets.create - ); - } else { - registerCustomScriptlets.promise = registerCustomScriptlets.create(); - } - registerCustomScriptlets.promise = registerCustomScriptlets.promise.then(worlds => - registerCustomScriptlets.register(worlds, none, notNone) - ); - return registerCustomScriptlets.promise; +export function setSandboxFilters(text = '') { + text = text.trim(); + return text !== '' + ? localWrite('sandboxFilters', text) + : localRemove('sandboxFilters') } - -registerCustomScriptlets.register = async function(worlds, none, notNone) { - if ( Boolean(worlds) === false ) { return; } - const toAdd = []; - const prepare = world => { - let { hostnames } = world; - let excludeHostnames = []; - if ( none.has('all-urls') ) { - hostnames = intersectHostnameIters(hostnames, notNone); - } else if ( none.size !== 0 ) { - hostnames = [ ...subtractHostnameIters(hostnames, none) ]; - excludeHostnames = Array.from(none); - } - if ( hostnames.length === 0 ) { return; } - const directive = { - allFrames: true, - js: [ { code: world.code } ], - matches: matchesFromHostnames(hostnames), - runAt: 'document_start', - }; - if ( excludeHostnames.length !== 0 ) { - directive.excludeMatches = matchesFromHostnames(excludeHostnames); - } - return directive; - }; - if ( worlds.ISOLATED ) { - const directive = prepare(worlds.ISOLATED); - if ( directive ) { - directive.id = 'user.isolated'; - directive.world = 'USER_SCRIPT'; - toAdd.push(directive); - } - } - if ( worlds.MAIN ) { - const directive = prepare(worlds.MAIN); - if ( directive ) { - directive.id = 'user.main'; - directive.world = 'MAIN'; - toAdd.push(directive); - } - } - if ( toAdd.length === 0 ) { return; } - await browser.userScripts.register(toAdd).then(( ) => { - ubolLog(`Registered userscript ${toAdd.map(v => v.id)}`); - }); -}; - -registerCustomScriptlets.create = async function() { - const toRemove = await browser.userScripts.getScripts(); - if ( toRemove.length !== 0 ) { - await browser.userScripts.unregister(); - ubolLog(`Unregistered userscript ${toRemove.map(v => v.id)}`); - } - const customFilters = await getAllCustomFilters(); - if ( customFilters.some(a => a[1].some(b => isScriptlet(b))) === false ) { return; } - const { promise: offscreenPromise, resolve: offscreenResolve } = Promise.withResolvers(); - const handler = (msg, sender, callback) => { - if ( typeof msg !== 'object' ) { return; } - switch ( msg?.what ) { - case 'getAllCustomFilters': - getAllCustomFilters().then(result => { - callback(result); - }); - break; - case 'registerCustomScriptlets': - offscreenResolve(msg); - break; - default: - break; - } - }; - const { promise: timeoutPromise, resolve: timeoutResolve } = Promise.withResolvers(); - self.setTimeout(timeoutResolve, 1000); - runtime.onMessage.addListener(handler); - const [ worlds ] = await Promise.all([ - Promise.race([ offscreenPromise, timeoutPromise ]), - browser.offscreen.createDocument({ - url: '/js/offscreen/compile-scriptlets.html', - reasons: [ 'WORKERS' ], - justification: 'To compile custom user script-based filters in a modular way from service worker (service workers do not allow dynamic module import)', - }), - ]); - runtime.onMessage.removeListener(handler); - await browser.offscreen.closeDocument(); - return worlds; -}; - -registerCustomScriptlets.promise = null; diff --git a/platform/mv3/extension/js/imported-lists.js b/platform/mv3/extension/js/imported-lists.js new file mode 100644 index 0000000000000..1378990137b2c --- /dev/null +++ b/platform/mv3/extension/js/imported-lists.js @@ -0,0 +1,249 @@ +/******************************************************************************* + + uBlock Origin Lite - a comprehensive, MV3-compliant content blocker + Copyright (C) 2026-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock +*/ + +import { + localKeys, + localRead, + localRemove, + localWrite, +} from './ext.js'; + +import { + registerJob, + removeJob, +} from './alarms.js'; + +import { ubolLog } from './debug.js'; + +/******************************************************************************/ + +const MS_PER_DAY = 24 * 60 * 60 * 1000; + +/******************************************************************************/ + +async function getCompiledListIds() { + const out = []; + const prefix = 'rulesets.imported.compiled.'; + const keys = await localKeys(); + for ( const key of keys ) { + if ( key.startsWith(prefix) === false ) { continue; } + out.push(key.slice(prefix.length)); + } + return out; +} + +/******************************************************************************/ + +async function scheduleImportedListsUpdate(lists) { + let earlierTime = 0; + for ( const list of lists ) { + if ( list.enabled !== true ) { continue; } + const updateTime = list.time.updated + list.expires * MS_PER_DAY; + if ( earlierTime !== 0 && earlierTime < updateTime ) { continue; } + earlierTime = updateTime; + } + if ( earlierTime ) { + return registerJob('updateImportedLists', earlierTime); + } + return removeJob('updateImportedLists'); +} + +/******************************************************************************/ + +export async function getEnabledImportedLists() { + const importedLists = await localRead('rulesets.imported') || []; + return importedLists.filter(a => a.enabled); +} + +/******************************************************************************/ + +export async function getImportedLists() { + const importedLists = await localRead('rulesets.imported') || []; + return importedLists || []; +} + +/******************************************************************************/ + +export async function updateEnabledImportedLists(toEnable, toDisable) { + const importedLists = await getImportedLists(); + const reImported = /^[a-z-]+:\/\//; + const enableRulesetIds = toEnable.filter(a => reImported.test(a)); + const disableRulesetIds = toDisable.filter(a => reImported.test(a)); + if ( enableRulesetIds.length === 0 ) { + if ( disableRulesetIds.length === 0 ) { return false; } + } + let modified = false; + for ( const list of importedLists ) { + if ( toEnable.includes(list.id) ) { + if ( list.enabled === true ) { continue; } + list.enabled = true; + modified = true; + } else if ( toDisable.includes(list.id) ) { + if ( list.enabled !== true ) { continue; } + list.enabled = false; + modified = true; + } + } + if ( modified ) { + await saveImportedLists(importedLists); + } + return modified; +} + +/******************************************************************************/ + +export async function saveImportedLists(lists) { + const compiledLists = await getCompiledListIds(); + const enabledListIds = lists.filter(a => a.enabled).map(a => a.id); + const toRemove = []; + for ( const listid of compiledLists ) { + if ( enabledListIds.includes(listid) ) { continue; } + toRemove.push(`rulesets.imported.compiled.${listid}`); + } + await Promise.all([ + toRemove.length ? localRemove(toRemove) : false, + localWrite('rulesets.imported', lists), + scheduleImportedListsUpdate(lists), + ]); +} + +/******************************************************************************/ + +export async function enableImportedRulesets(rulesets) { + const toEnable = new Set(rulesets); + const importedLists = await getImportedLists(); + let modified = 0; + for ( const list of importedLists ) { + if ( toEnable.has(list.id) ) { + if ( list.enabled === true ) { continue; } + list.enabled = true; + modified += 1; + } else { + if ( list.enabled !== true ) { continue; } + list.enabled = false; + modified += 1; + } + } + if ( modified ) { + await saveImportedLists(importedLists); + } + return modified; +} + +/******************************************************************************/ + +export async function getImportedListCompiledData(listid) { + return { + listid, + serialized: await localRead(`rulesets.imported.compiled.${listid}`), + }; +} + +/******************************************************************************/ + +export async function updateImportedListData(listid, details) { + if ( details.compiled ) { + await localWrite(`rulesets.imported.compiled.${listid}`, details.compiled); + } else { + await localRemove(`rulesets.imported.compiled.${listid}`); + } + const lists = await getImportedLists(); + const list = lists.find(a => listid === a.id); + if ( list === undefined ) { return; } + list.time.updated = Date.now(); + if ( details.title ) { list.name = details.title; } + if ( details.homeURL ) { list.homeURL = details.homeURL; } + if ( details.expires ) { list.expires = details.expires; } + if ( details.filterStats ) { list.filters = details.filterStats; } + if ( details.ruleStats ) { list.rules = details.ruleStats; } + await saveImportedLists(lists); + return { listid }; +} + +/******************************************************************************/ + +// URL will be ruleset id + +export async function addImportedLists(toImport) { + const lists = await getImportedLists(); + const beforeCount = lists.length; + for ( let details of toImport ) { + if ( typeof details === 'string' ) { + details = { url: details }; + } + const { url } = details; + if ( lists.some(a => a.id === url) ) { continue; } + lists.push({ + id: url, + name: details.name ?? url, + group: 'imported', + enabled: false, + homeURL: details.homeURL ?? '', + expires: 7, + time: { + added: Date.now(), + updated: 0, + }, + filters: { + total: 0, + accepted: 0, + rejected: 0, + }, + rules: { + total: 0, + plain: 0, + regex: 0, + }, + }); + } + if ( lists.length !== beforeCount ) { + await saveImportedLists(lists); + } + return true; +} + +/******************************************************************************/ + +export async function removeImportedLists(ids) { + const setOfIds = new Set(Array.isArray(ids) ? ids : [ ids ]); + const beforeLists = await getImportedLists(); + const afterLists = beforeLists.filter(a => setOfIds.has(a.id) === false); + if ( afterLists.length === beforeLists.length ) { return false; } + await saveImportedLists(afterLists); + return true; +} + +/******************************************************************************/ + +export async function updateImportedLists() { + const lists = await getEnabledImportedLists(); + const now = Date.now(); + const toUpdate = []; + for ( const list of lists ) { + const updateTime = list.time.updated + list.expires * MS_PER_DAY; + if ( updateTime > now ) { continue; } + toUpdate.push(list.id); + } + if ( toUpdate.length === 0 ) { return 0; } + await localRemove(toUpdate.map(a => `rulesets.imported.compiled.${a}`)); + ubolLog(`Will update imported filter lists: ${toUpdate.join()}`); + return toUpdate.length; +} diff --git a/platform/mv3/extension/js/mode-manager.js b/platform/mv3/extension/js/mode-manager.js index 8a7831a0dba81..3baddd866edbd 100644 --- a/platform/mv3/extension/js/mode-manager.js +++ b/platform/mv3/extension/js/mode-manager.js @@ -38,6 +38,7 @@ import { } from './config.js'; import { adminReadEx } from './admin.js'; +import { deferredTasks } from './deferred-tasks.js'; import { filteringModesToDNR } from './ruleset-manager.js'; import { hasBroadHostPermissions } from './ext-utils.js'; @@ -103,6 +104,22 @@ const unserializeModeDetails = details => { /******************************************************************************/ +function fixFilteringModeDetails(details) { + const { none, basic, optimal, complete } = unserializeModeDetails(details); + // Descendant hostnames cannot override no-filtering mode + for ( const exclude of none ) { + basic.delete(exclude); + pruneDescendantHostnamesFromSet(exclude, basic); + optimal.delete(exclude); + pruneDescendantHostnamesFromSet(exclude, optimal); + complete.delete(exclude); + pruneDescendantHostnamesFromSet(exclude, complete); + } + return { none, basic, optimal, complete }; +} + +/******************************************************************************/ + function lookupFilteringMode(filteringModes, hostname) { const { none, basic, optimal, complete } = filteringModes; if ( hostname === 'all-urls' ) { @@ -258,13 +275,23 @@ export async function readFilteringModeDetails(bypassCache = false) { if ( adminNoFiltering.includes('-*') ) { userModes.none.clear(); } - for ( const hn of adminNoFiltering ) { - if ( hn.charAt(0) === '-' ) { - userModes.none.delete(hn.slice(1)); - } else { - applyFilteringMode(userModes, hn, 0); + let modified = false; + for ( const token of adminNoFiltering ) { + if ( token.charAt(0) === '-' ) { + const hn = token.slice(1); + if ( userModes.none.has(hn) === false ) { continue; } + userModes.none.delete(hn); + modified = true; + } else if ( userModes.none.has(token) === false ) { + userModes.none.add(token); + modified = true; } } + if ( modified ) { + deferredTasks.add('registerContentScripts'); + deferredTasks.add('registerUserScripts'); + } + userModes = fixFilteringModeDetails(userModes); } filteringModesToDNR(userModes); sessionWrite('filteringModeDetails', serializeModeDetails(userModes)); @@ -308,7 +335,9 @@ export async function getFilteringModeDetails(serializable = false) { } export async function setFilteringModeDetails(details) { - await localWrite('filteringModeDetails', serializeModeDetails(details)); + await localWrite('filteringModeDetails', + serializeModeDetails(fixFilteringModeDetails(details)) + ); await readFilteringModeDetails(true); } diff --git a/platform/mv3/extension/js/offscreen/compile-filters.html b/platform/mv3/extension/js/offscreen/compile-filters.html new file mode 100644 index 0000000000000..e20b1aa97187f --- /dev/null +++ b/platform/mv3/extension/js/offscreen/compile-filters.html @@ -0,0 +1,16 @@ + + + + + + +Filters compiler + + + + + + + + + diff --git a/platform/mv3/extension/js/offscreen/compile-filters.js b/platform/mv3/extension/js/offscreen/compile-filters.js new file mode 100644 index 0000000000000..2305a7ce7433e --- /dev/null +++ b/platform/mv3/extension/js/offscreen/compile-filters.js @@ -0,0 +1,514 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2026-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock +*/ + +import * as makeScriptlets from './make-scriptlets.js'; +import * as s14e from '../../lib/s14e-serializer.js'; +import * as sfp from '../static-filtering-parser.js'; +import { minimizeRules, minimizeRuleset, validateRules } from '../ubo-parser.js'; +import { fetchList } from './fetch-list.js'; +import { getTrustedTokens } from '../trusted-tokens.js'; +import { makeCosmeticScripts } from './make-cosmetic-filters.js'; +import { parseNetworkFilter } from '../ubo-parser.js'; +import { safeReplace } from './safe-replace.js'; + +/******************************************************************************/ + +const browser = (self.browser || self.chrome); + +const resourceTypes = await browser.runtime.sendMessage({ + what: 'compileFilters:getResourceTypes' +}); + +/******************************************************************************/ + +function parseExpires(s) { + const matches = s.match(/(\d+)\s*([wdhm]?)/i); + if ( matches === null ) { return; } + let updateAfter = parseInt(matches[1], 10); + if ( updateAfter === 0 ) { return; } + if ( matches[2] === 'w' ) { + updateAfter *= 7 * 24; + } else if ( matches[2] === 'h' ) { + updateAfter = Math.max(updateAfter, 4) / 24; + } else if ( matches[2] === 'm' ) { + updateAfter = Math.max(updateAfter, 240) / 1440; + } + return updateAfter; +} + +/******************************************************************************/ + +function extractMetadataFromList(content, fields) { + const out = {}; + const head = content.slice(0, 1024); + for ( let field of fields ) { + field = field.replace(/\s+/g, '-'); + const re = new RegExp(`^(?:! *|# +)${field.replace(/-/g, '(?: +|-)')}: *(.+)$`, 'im'); + const match = re.exec(head); + let value = match && match[1].trim() || undefined; + if ( value !== undefined && value.startsWith('%') ) { + value = undefined; + } + field = field.toLowerCase().replace( + /-[a-z]/g, s => s.charAt(1).toUpperCase() + ); + out[field] = value; + } + // Pre-process known fields + if ( out.lastModified ) { + out.lastModified = (new Date(out.lastModified)).getTime() || 0; + } + if ( out.expires ) { + out.expires = parseExpires(out.expires); + } + return out; +} + +/******************************************************************************/ + +function compileScriptletFilter(parser, output) { + if ( parser.hasOptions() === false ) { return; } + const exception = parser.isException(); + const args = parser.getScriptletArgs(); + const argsToken = JSON.stringify(args); + for ( const { hn, not, bad } of parser.getExtFilterDomainIterator() ) { + if ( bad ) { continue; } + if ( exception ) { continue; } + const details = output.get(argsToken) ?? {}; + if ( details.args === undefined ) { + details.args = args; + details.trustedSource = parser.options.trustedSource; + output.set(argsToken, details); + } + if ( not ) { + details.excludeMatches ??= []; + details.excludeMatches.push(hn); + continue; + } + details.matches ??= []; + if ( details.matches[0] === '*' ) { continue; } + if ( hn !== '*' ) { + details.matches.push(hn); + } else if ( parser.options.trustedSource ) { + details.matches = [ '*' ]; + } + } +} + +/******************************************************************************/ + +export function compileCosmeticFilter(parser, output) { + const { compiled, exception } = parser.result; + if ( compiled === undefined ) { return; } + const sanitized = sanitizeCompiledCosmeticFilter(compiled); + const matches = []; + const excludeMatches = []; + for ( const { hn, not, bad } of parser.getExtFilterDomainIterator() ) { + if ( bad ) { continue; } + if ( not && exception ) { continue; } + if ( not || exception ) { + excludeMatches.push(hn); + } else if ( hn === '*' ) { + if ( parser.options.trustedSource !== true ) { continue; } + matches.length = 0; + matches.push('*'); + } else { + if ( matches[0] === '*' ) { continue; } + matches.push(hn); + } + } + // This should not happen + if ( matches.length === 0 && excludeMatches.length === 0 ) { return; } + // Only negated hostnames => generic cosmetic filter + if ( exception === false ) { + if ( matches.length === 0 && excludeMatches.length !== 0 ) { return; } + } + const details = output.get(sanitized) ?? {}; + if ( details.matches === undefined ) { + details.matches = []; + details.excludeMatches = []; + output.set(sanitized, details); + } + if ( matches.length ) { + if ( matches.includes('*') ) { + details.matches = [ '*' ]; + } else if ( details.matches.includes('*') === false ) { + details.matches.push(...matches); + } + } + if ( excludeMatches.length ) { + details.excludeMatches.push(...excludeMatches); + } +} + +function sanitizeCompiledCosmeticFilter(compiled) { + if ( compiled.startsWith('{') === false ) { return compiled; } + const parsed = JSON.parse(compiled); + parsed.raw = undefined; + return JSON.stringify(parsed); +} + +/******************************************************************************/ + +export function compileFilters(listid, text, context = {}) { + if ( Boolean(text) === false ) { return; } + + const parser = new sfp.AstFilterParser(context); + + const unminimizedRules = []; + const specificCosmeticDetails = new Map(); + const scriptletDetails = new Map(); + + const lines = text.split(/\n/).map(a => a.trim()); + const filterStats = { + total: 0, + accepted: 0, + rejected: 0, + }; + for ( const line of lines ) { + parser.parse(line); + if ( parser.hasError() ) { continue; } + if ( parser.isScriptletFilter() ) { + if ( parser.hasOptions() === false ) { continue; } + compileScriptletFilter(parser, scriptletDetails); + continue; + } + if ( parser.isCosmeticFilter() ) { + if ( parser.hasOptions() === false ) { continue; } + compileCosmeticFilter(parser, specificCosmeticDetails); + continue; + } + if ( parser.isNetworkFilter() ) { + filterStats.total += 1; + const result = parseNetworkFilter(parser, { resourceTypes }, unminimizedRules); + if ( result ) { + filterStats.accepted += 1; + } else { + filterStats.rejected += 1; + } + continue; + } + } + + let minimizedRules = minimizeRuleset(unminimizedRules); + minimizedRules = minimizeRules(minimizedRules); + minimizedRules = validateRules(minimizedRules); + const regexRuleCount = minimizedRules.reduce((a, b) => { + return b.condition.regexFilter ? a+1 : a; + }, 0); + + return { + filterStats, + ruleStats: { + total: minimizedRules.length, + plain: minimizedRules.length - regexRuleCount, + regex: regexRuleCount, + }, + dnrRules: minimizedRules, + specificCosmeticDetails, + scriptletDetails, + }; +} + +/******************************************************************************/ + +export async function toMv3Data(rulesetid, compiledData) { + const isolated = []; + const main = []; + + if ( Boolean(compiledData) === false ) { return; } + + if ( compiledData.scriptletDetails.size !== 0 ) { + for ( const details of compiledData.scriptletDetails.values() ) { + makeScriptlets.compile(rulesetid, details); + } + const template = await fetch('./scriptlet.template.js').then(response => + response.text() + ); + const result = makeScriptlets.commit(rulesetid, template); + if ( result.ISOLATED ) { + const { hasRegexes, hasAncestors, hasEntities } = result.ISOLATED; + const hostnames = hasRegexes || hasAncestors || hasEntities || + result.ISOLATED.hostnames.includes('*') + ? '*' + : result.ISOLATED.hostnames; + isolated.push({ + id: `${rulesetid}-isolated-scriptlets`, + code: result.ISOLATED.code, + hostnames, + }); + } + if ( result.MAIN ) { + const { hasRegexes, hasAncestors, hasEntities } = result.MAIN; + const hostnames = hasRegexes || hasAncestors || hasEntities || + result.MAIN.hostnames.includes('*') + ? '*' + : result.MAIN.hostnames; + main.push({ + id: `${rulesetid}-main-scriptlets`, + code: result.MAIN.code, + hostnames, + }); + } + makeScriptlets.reset(); + } + + if ( compiledData.specificCosmeticDetails.size ) { + const result = makeCosmeticScripts(rulesetid, compiledData.specificCosmeticDetails); + if ( result ) { + const [ + cssAPI, + isolatedAPI, + proceduralAPI, + template, + ] = await Promise.all([ + fetch('../scripting/css-api.js').then(response => response.text()), + fetch('../scripting/isolated-api.js').then(response => response.text()), + fetch('../scripting/css-procedural-api.js').then(response => response.text()), + fetch('./css-compiled.template.js').then(response => response.text()), + ]); + const code = [ + cssAPI, + isolatedAPI, + proceduralAPI, + safeReplace(template, 'self.$cssSpecificData$', JSON.stringify(result.data)), + ].join('\n'); + const hostnames = result.data.hasEntities || result.data.regexes.length + ? '*' + : result.data.hostnames; + isolated.push({ + id: `${rulesetid}-css-specific`, + code, + hostnames, + }); + } + } + + const output = {} + if ( compiledData.dnrRules.length ) { + output.dnrRules = minimizeRuleset(compiledData.dnrRules); + output.dnrRules = minimizeRules(output.dnrRules); + output.dnrRules = validateRules(output.dnrRules); + } + if ( isolated.length ) { + output.isolated = isolated; + } + if ( main.length ) { + output.main = main; + } + + return output; +} + +/******************************************************************************/ + +async function updateList(list) { + const context = { + env: [ + 'chromium', + 'native_css_has', + 'mv3', + 'ublock', + 'ubol', + ], + }; + const asset = { urls: [ list.id ] }; + const text = await fetchList(context, asset, ( ) => { + browser.runtime.sendMessage({ what: 'keepAlive' }); + }); + if ( Boolean(text) === false ) { return; } + + const metadata = extractMetadataFromList(text, [ + 'Expires', + 'Homepage', + 'Title', + ]) + if ( /^https?:\/\/\S+/.test(metadata.homepage) === false ) { + metadata.homepage = undefined; + } + + const compiled = compileFilters(list.id, text, { + nativeCssHas: true, + trustedTokens: getTrustedTokens(), + }); + if ( Boolean(compiled) === false ) { return; } + + await browser.runtime.sendMessage({ + what: 'compileFilters:updateImportedListData', + listid: list.id, + compiled: s14e.serialize(compiled, { compress: true }), + title: metadata.title, + homeURL: metadata.homepage, + expires: metadata.expires || 7, + filterStats: compiled.filterStats, + ruleStats: compiled.ruleStats, + }); + + return compiled; +} + +/******************************************************************************/ + +async function getCompiledListData(list) { + const result = await browser.runtime.sendMessage({ + what: 'compileFilters:getImportedListCompiledData', + listid: list.id, + }); + if ( Boolean(result?.serialized) === false ) { + return updateList(list); + } + return s14e.deserialize(result.serialized); +} + +/******************************************************************************/ + +function mergeCompiledData(to, from) { + if ( from.dnrRules ) { + if ( to.dnrRules ) { + to.dnrRules = to.dnrRules.concat(from.dnrRules); + } else { + to.dnrRules = from.dnrRules; + } + } + if ( from.specificCosmeticDetails ) { + if ( to.specificCosmeticDetails ) { + for ( const [ fromSelector, fromDetails ] of from.specificCosmeticDetails ) { + const toDetails = to.specificCosmeticDetails.get(fromSelector); + if ( toDetails ) { + if ( toDetails.matches?.length ) { + toDetails.matches = toDetails.matches.concat(fromDetails.matches); + } else { + toDetails.matches = fromDetails.matches; + } + if ( toDetails.excludeMatches?.length ) { + toDetails.excludeMatches = toDetails.excludeMatches.concat(fromDetails.excludeMatches); + } else { + toDetails.excludeMatches = fromDetails.excludeMatches; + } + } else { + to.specificCosmeticDetails.set(fromSelector, fromDetails); + } + } + } else { + to.specificCosmeticDetails = from.specificCosmeticDetails; + } + } + if ( from.scriptletDetails ) { + if ( to.scriptletDetails ) { + for ( const [ fromKey, fromDetails ] of from.scriptletDetails ) { + const toDetails = to.scriptletDetails.get(fromKey); + if ( toDetails ) { + toDetails.trustedSource ||= fromDetails.trustedSource; + if ( toDetails.matches?.length ) { + toDetails.matches = toDetails.matches.concat(fromDetails.matches); + } else { + toDetails.matches = fromDetails.matches; + } + if ( toDetails.excludeMatches?.length ) { + toDetails.excludeMatches = toDetails.excludeMatches.concat(fromDetails.excludeMatches); + } else { + toDetails.excludeMatches = fromDetails.excludeMatches; + } + } else { + to.scriptletDetails.set(fromKey, fromDetails); + } + } + } else { + to.scriptletDetails = from.scriptletDetails; + } + } +} + +/******************************************************************************/ + +async function compileImportedList() { + const lists = await browser.runtime.sendMessage({ + what: 'compileFilters:getEnabledImportedLists' + }); + if ( Boolean(lists?.length) === false ) { return; } + const promises = []; + for ( const list of lists ) { + if ( list.enabled !== true ) { continue; } + promises.push(getCompiledListData(list)); + } + const compiledData = await Promise.all(promises); + const toMerge = compiledData.filter(a => a); + if ( toMerge.length === 0 ) { return; } + const merged = toMerge[0]; + while ( toMerge.length > 1 ) { + mergeCompiledData(merged, toMerge.pop()); + } + return merged; +} + +/******************************************************************************/ + +async function compileSandboxFilters() { + const text = await browser.runtime.sendMessage({ + what: 'compileFilters:getUserList' + }); + if ( Boolean(text) === false ) { return; } + return compileFilters('sandbox', text, { + localSource: true, + nativeCssHas: true, + trustedSource: true, + }); +} + +/******************************************************************************/ + +(async ( ) => { + const [ + sandboxResult, + importedResult, + ] = await Promise.all([ + compileSandboxFilters(), + compileImportedList(), + ]); + const sandboxCompiled = await toMv3Data('sandbox', sandboxResult) ?? {}; + const importedCompiled = await toMv3Data('imported', importedResult) ?? {}; + const msg = { + what: 'compileFilters:result', + sandbox: {}, + imported: {}, + }; + if ( sandboxCompiled.isolated?.length ) { + msg.sandbox.ISOLATED = sandboxCompiled.isolated; + } + if ( sandboxCompiled.main?.length ) { + msg.sandbox.MAIN = sandboxCompiled.main; + } + if ( sandboxCompiled.dnrRules?.length ) { + msg.sandbox.dnrRules = sandboxCompiled.dnrRules; + } + if ( importedCompiled.isolated?.length ) { + msg.imported.ISOLATED = importedCompiled.isolated; + } + if ( importedCompiled.main?.length ) { + msg.imported.MAIN = importedCompiled.main; + } + if ( importedCompiled.dnrRules?.length ) { + msg.imported.dnrRules = importedCompiled.dnrRules; + } + browser.runtime.sendMessage(msg); +})(); + +/******************************************************************************/ diff --git a/platform/mv3/extension/js/offscreen/compile-scriptlets.html b/platform/mv3/extension/js/offscreen/compile-scriptlets.html deleted file mode 100644 index f1e1ad2d0aa8d..0000000000000 --- a/platform/mv3/extension/js/offscreen/compile-scriptlets.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - -Scriptlet filters compiler - - - - - - - - diff --git a/platform/mv3/extension/js/offscreen/compile-scriptlets.js b/platform/mv3/extension/js/offscreen/compile-scriptlets.js deleted file mode 100644 index 989b1f4aa36ce..0000000000000 --- a/platform/mv3/extension/js/offscreen/compile-scriptlets.js +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************* - - uBlock Origin - a comprehensive, efficient content blocker - Copyright (C) 2026-present Raymond Hill - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see {http://www.gnu.org/licenses/}. - - Home: https://github.com/gorhill/uBlock -*/ - -import * as makeScriptlet from '../make-scriptlets.js'; -import * as sfp from '../static-filtering-parser.js'; - -/******************************************************************************/ - -(async ( ) => { - const parser = new sfp.AstFilterParser({ trustedSource: true }); - const scriptletDetails = new Map(); - - const data = await chrome.runtime.sendMessage({ what: 'getAllCustomFilters' }); - - for ( const [ hostname, selectors ] of data ) { - for ( const selector of selectors ) { - if ( selector.startsWith('+js') === false ) { continue; } - parser.parse(`##${selector}`); - if ( parser.isScriptletFilter() === false ) { continue; } - const args = parser.getScriptletArgs(); - const argsToken = JSON.stringify(args); - const details = scriptletDetails.get(argsToken) || { - args, - matches: [], - trustedSource: true, - }; - if ( details.matches.length === 0 ) { - scriptletDetails.set(argsToken, details); - } - details.matches.push(hostname); - } - } - - for ( const details of scriptletDetails.values() ) { - makeScriptlet.compile('user', details); - } - - const template = await fetch('../scriptlet.template.js').then(response => - response.text() - ); - const result = makeScriptlet.commit('user', template); - chrome.runtime.sendMessage(Object.assign({ what: 'registerCustomScriptlets', }, result)); -})(); diff --git a/platform/mv3/extension/js/offscreen/css-compiled.template.js b/platform/mv3/extension/js/offscreen/css-compiled.template.js new file mode 100644 index 0000000000000..8a264353ca6a8 --- /dev/null +++ b/platform/mv3/extension/js/offscreen/css-compiled.template.js @@ -0,0 +1,114 @@ +/******************************************************************************* + + uBlock Origin Lite - a comprehensive, MV3-compliant content blocker + Copyright (C) 2019-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock +*/ + +// Important! +// Isolate from global scope +(async function uBOL_cssCompiled() { + +/******************************************************************************/ + +const cssSpecificData = self.$cssSpecificData$; + +/******************************************************************************/ + +const { isolatedAPI } = self; +const thisHostname = document.location.hostname || ''; +const selectors = new Set(); +const exceptions = new Set(); + +const selectorsFromListIndex = ilist => { + const list = JSON.parse(`[${cssSpecificData.selectorLists[ilist]}]`); + for ( const iselector of list ) { + if ( iselector >= 0 ) { + const selector = cssSpecificData.selectors[iselector]; + if ( exceptions.has(selector) ) { continue; } + selectors.add(selector); + } else { + const exception = cssSpecificData.selectors[~iselector]; + exceptions.add(exception); + selectors.delete(exception); + } + } +}; + +const { hostnames, regexes } = cssSpecificData; +if ( hostnames.length ) { + const selectorsFromHostnames = (haystack, needles) => { + let listref = -1; + for ( const needle of needles ) { + listref = isolatedAPI.binarySearch(haystack, needle, listref); + if ( listref >= 0 ) { + selectorsFromListIndex(cssSpecificData.selectorListRefs[listref]); + } else { + listref = ~listref + 1; + } + } + }; + selectorsFromHostnames(hostnames, isolatedAPI.contexts.hostnames); + if ( cssSpecificData.hasEntities ) { + selectorsFromHostnames(hostnames, isolatedAPI.contexts.entities); + } +} +for ( let i = 0, n = regexes.length; i < n; i += 3 ) { + if ( thisHostname.includes(regexes[i+0]) === false ) { continue; } + if ( typeof regexes[i+1] === 'string' ) { + regexes[i+1] = new RegExp(regexes[i+1]); + } + if ( regexes[i+1].test(thisHostname) === false ) { continue; } + selectorsFromListIndex(cssSpecificData, regexes[i+2]); +} + +const s = []; +const p = []; +for ( const selector of selectors ) { + if ( selector.startsWith('{') ) { + p.push(JSON.parse(selector)); + } else { + s.push(selector); + } +} + +if ( s.length !== 0 ) { + self.cssAPI.insert(`${s.join(',\n')}{display:none!important;}`); +} + +if ( p.length !== 0 ) { + await self.ProceduralFiltererAPI; + self.listsProceduralFiltererAPI = new self.ProceduralFiltererAPI(); + + const declaratives = p.filter(a => a.cssable); + if ( declaratives.length !== 0 ) { + self.listsProceduralFiltererAPI.addDeclaratives(declaratives); + } + const procedurals = p.filter(a => !a.cssable); + if ( procedurals.length !== 0 ) { + self.listsProceduralFiltererAPI.addProcedurals(procedurals); + } +} + +self.isolatedAPI = undefined; +self.ProceduralFiltererAPI = undefined; + +/******************************************************************************/ + +})(); + +void 0; diff --git a/platform/mv3/extension/js/offscreen/fetch-list.js b/platform/mv3/extension/js/offscreen/fetch-list.js new file mode 100644 index 0000000000000..ecb58fd5e032d --- /dev/null +++ b/platform/mv3/extension/js/offscreen/fetch-list.js @@ -0,0 +1,113 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2022-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock +*/ + +import * as sfp from '../static-filtering-parser.js'; + +/******************************************************************************/ + +async function fetchText(url, progressFn) { + const response = await fetch(url).catch(( ) => { }); + if ( response?.ok !== true ) { + return { url, error: `Fetching from "${url}" failed` }; + } + const reader = response.body.getReader(); + const decoder = new TextDecoder(); + const parts = []; + try { + for (;;) { + const { done, value } = await reader.read(); + if ( done ) { break; } + parts.push(decoder.decode(value, { stream: true })); + if ( progressFn ) { progressFn(); } + } + } catch { + return { url, error: `Fetching content from "${url}" failed` }; + } + parts.push(decoder.decode()); + return { url, content: parts.join('') }; +} + +/******************************************************************************/ + +function isTrusted(context, asset, url) { + if ( asset.trusted ) { return true; } + if ( Array.isArray(context.trustedPrefixes) === false ) { return false; } + for ( const prefix of context.trustedPrefixes ) { + if ( url.startsWith(prefix) ) { return true; } + } + return false; +} + +/******************************************************************************/ + +export async function fetchList(context, asset, progressFn) { + // Mind commit if present + const effectiveURL = url => { + return asset.commit + ? url.replace('{commit}', asset.commit) + : url; + }; + + // Remember fetched URLs + const fetchedURLs = new Set(); + + // Fetch list and expand `!#include` directives + let parts = asset.urls.map(url => ({ url: effectiveURL(url) })); + while ( parts.every(v => typeof v === 'string') === false ) { + const newParts = []; + for ( const part of parts ) { + if ( typeof part === 'string' ) { + newParts.push(effectiveURL(part)); + continue; + } + if ( fetchedURLs.has(effectiveURL(part.url)) ) { + newParts.push(''); + continue; + } + fetchedURLs.add(effectiveURL(part.url)); + if ( isTrusted(context, asset, part.url) && context.secret ) { + newParts.push(`!#trusted on ${context.secret}`); + } + newParts.push( + fetchText(effectiveURL(part.url), progressFn).then(details => { + const { url, error } = details; + if ( error !== undefined ) { return details; } + const content = details.content.trim(); + if ( /^<.*>$/.test(content) ) { + return { url, error: `Bad content: ${url}` }; + } + return { url, content }; + }) + ); + if ( context.secret ) { + newParts.push(`!#trusted off ${context.secret}`); + } + } + parts = await Promise.all(newParts); + if ( parts.some(v => typeof v === 'object' && v.error) ) { return; } + parts = sfp.utils.preparser.expandIncludes(parts, context.env); + } + const text = parts.join('\n'); + + return text; +} + +/******************************************************************************/ diff --git a/platform/mv3/extension/js/offscreen/make-cosmetic-filters.js b/platform/mv3/extension/js/offscreen/make-cosmetic-filters.js new file mode 100644 index 0000000000000..540a5efa357a4 --- /dev/null +++ b/platform/mv3/extension/js/offscreen/make-cosmetic-filters.js @@ -0,0 +1,109 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2022-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock +*/ + +import { hostnameCompare, isHnRegexOrPath } from './make-utils.js'; +import { literalStrFromRegex } from './regex-analyzer.js'; + +/******************************************************************************/ + +export function makeCosmeticScripts(rulesetId, mapin) { + if ( mapin === undefined ) { return; } + if ( mapin.size === 0 ) { return; } + + // Collate all distinct selectors + const allSelectors = new Map(); + const allHostnames = new Map(); + const allRegexesOrPaths = new Map(); + let hasEntities = false; + + const storeHostnameSelectorPair = (hn, iSelector) => { + if ( isHnRegexOrPath(hn) ) { + if ( allRegexesOrPaths.has(hn) === false ) { + allRegexesOrPaths.set(hn, new Set()); + } + allRegexesOrPaths.get(hn).add(iSelector); + } else { + if ( allHostnames.has(hn) === false ) { + allHostnames.set(hn, new Set()); + } + allHostnames.get(hn).add(iSelector); + hasEntities ||= hn.endsWith('.*'); + } + }; + + for ( const [ selector, details ] of mapin ) { + if ( details.rejected ) { continue; } + if ( allSelectors.has(selector) === false ) { + allSelectors.set(selector, allSelectors.size); + } + const iSelector = allSelectors.get(selector); + if ( details.matches ) { + for ( const hn of details.matches ) { + storeHostnameSelectorPair(hn, iSelector); + } + } + if ( details.excludeMatches ) { + for ( const hn of details.excludeMatches ) { + storeHostnameSelectorPair(hn, ~iSelector); + } + } + } + const allSelectorLists = new Map(); + + const ilistFromSelectorSet = selectorSet => { + const list = JSON.stringify(Array.from(selectorSet).sort()).slice(1, -1); + if ( allSelectorLists.has(list) === false ) { + allSelectorLists.set(list, allSelectorLists.size); + } + return allSelectorLists.get(list); + }; + + for ( const [ hn, selectorSet ] of allHostnames ) { + allHostnames.set(hn, ilistFromSelectorSet(selectorSet)); + } + for ( const [ regexOrPath, selectorSet ] of allRegexesOrPaths ) { + allRegexesOrPaths.set(regexOrPath, ilistFromSelectorSet(selectorSet)); + } + + const sortedHostnames = Array.from(allHostnames.keys()).toSorted(hostnameCompare); + + const data = { + rulesetId, + selectors: Array.from(allSelectors.keys()), + selectorLists: Array.from(allSelectorLists.keys()), + selectorListRefs: sortedHostnames.map(a => allHostnames.get(a)), + hostnames: sortedHostnames, + hasEntities, + regexes: Array.from(allRegexesOrPaths) + .filter(a => a[0].startsWith('/') && a[0].endsWith('/')) + .map(a => { + const restr = a[0].slice(1,-1); + return [ literalStrFromRegex(restr).slice(0,8), restr, a[1] ] + }).flat(), + }; + + return { + selectorCount: allSelectors.size, + hostnameCount: sortedHostnames.length, + regexCount: allRegexesOrPaths.size, + data, + }; +} diff --git a/platform/mv3/extension/js/make-scriptlets.js b/platform/mv3/extension/js/offscreen/make-scriptlets.js similarity index 84% rename from platform/mv3/extension/js/make-scriptlets.js rename to platform/mv3/extension/js/offscreen/make-scriptlets.js index 3859a14f7cc1d..dcd5d34334703 100644 --- a/platform/mv3/extension/js/make-scriptlets.js +++ b/platform/mv3/extension/js/offscreen/make-scriptlets.js @@ -19,7 +19,8 @@ Home: https://github.com/gorhill/uBlock */ -import { builtinScriptlets } from './resources/scriptlets.js'; +import { hostnameCompare, isHnRegexOrPath } from './make-utils.js'; +import { builtinScriptlets } from '../resources/scriptlets.js'; import { literalStrFromRegex } from './regex-analyzer.js'; import { safeReplace } from './safe-replace.js'; @@ -31,7 +32,7 @@ const worldTemplate = { scriptletFunctions: new Map(), allFunctions: new Map(), args: new Map(), - arglists: new Map(), + arglists: new Map([['',0]]), hostnames: new Map(), regexesOrPaths: new Map(), matches: new Set(), @@ -63,6 +64,29 @@ function createScriptletCoreCode(worldDetails, resourceEntry) { /******************************************************************************/ +function compileBroadExclusion(details) { + if ( Boolean(details.excludeMatches?.length) === false ) { return; } + for ( const worldDetails of Object.values(worlds) ) { + for ( const hn of details.excludeMatches ) { + if ( isHnRegexOrPath(hn) ) { + const refs = worldDetails.regexesOrPaths.get(hn) ?? new Set(); + if ( refs.size === 0 ) { + worldDetails.regexesOrPaths.set(hn, refs); + } + refs.add(0); + continue; + } + const refs = worldDetails.hostnames.get(hn) ?? new Set(); + if ( refs.size === 0 ) { + worldDetails.hostnames.set(hn, refs); + } + refs.add(0); + } + } +} + +/******************************************************************************/ + export function reset() { worlds.ISOLATED = structuredClone(worldTemplate); worlds.MAIN = structuredClone(worldTemplate); @@ -71,6 +95,9 @@ export function reset() { /******************************************************************************/ export function compile(rulesetId, details) { + if ( details.args.length === 0 ) { + return compileBroadExclusion(details); + } if ( details.args[0].endsWith('.js') === false ) { details.args[0] += '.js'; } @@ -107,7 +134,7 @@ export function compile(rulesetId, details) { const arglistIndex = worldDetails.arglists.get(arglistKey); if ( details.matches ) { for ( const hn of details.matches ) { - if ( hn.includes('/') ) { + if ( isHnRegexOrPath(hn) ) { worldDetails.matches.clear(); worldDetails.matches.add('*'); if ( worldDetails.regexesOrPaths.has(hn) === false ) { @@ -137,7 +164,7 @@ export function compile(rulesetId, details) { } if ( details.excludeMatches ) { for ( const hn of details.excludeMatches ) { - if ( hn.includes('/') ) { + if ( isHnRegexOrPath(hn) ) { if ( worldDetails.regexesOrPaths.has(hn) === false ) { worldDetails.regexesOrPaths.set(hn, new Set()); } @@ -160,11 +187,9 @@ export function commit(rulesetId, template) { const worldDetails = worlds[world]; const { scriptletFunctions, allFunctions, args, arglists } = worldDetails; if ( scriptletFunctions.size === 0 ) { continue; } - const hostnames = Array.from(worldDetails.hostnames).toSorted((a, b) => { - const d = a[0].length - b[0].length; - if ( d !== 0 ) { return d; } - return a[0] < b[0] ? -1 : 1; - }).map(a => ([ a[0], JSON.stringify(Array.from(a[1]).map(a => JSON.parse(a))).slice(1,-1)])); + const hostnames = Array.from(worldDetails.hostnames).toSorted((a, b) => + hostnameCompare(a[0], b[0]) + ).map(a => ([ a[0], JSON.stringify(Array.from(a[1]).map(a => JSON.parse(a))).slice(1,-1)])); const scriptletFromRegexes = Array.from(worldDetails.regexesOrPaths) .filter(a => a[0].startsWith('/') && a[0].endsWith('/')) .map(a => { @@ -175,7 +200,8 @@ export function commit(rulesetId, template) { JSON.stringify(Array.from(a[1])).slice(1,-1), ]; }).flat(); - let content = safeReplace(template, 'self.$hasEntities$', JSON.stringify(worldDetails.hasEntities)); + let content = safeReplace(template, 'self.$hasHostnames$', JSON.stringify(hostnames.length !== 0)); + content = safeReplace(content, 'self.$hasEntities$', JSON.stringify(worldDetails.hasEntities)); content = safeReplace(content, 'self.$hasAncestors$', JSON.stringify(worldDetails.hasAncestors)); content = safeReplace(content, 'self.$hasRegexes$', JSON.stringify(scriptletFromRegexes.length !== 0)); content = safeReplace(content, @@ -210,6 +236,9 @@ export function commit(rulesetId, template) { stats[world] = { code: content, hostnames: Array.from(worldDetails.matches).sort(), + hasRegexes: scriptletFromRegexes.length !== 0, + hasAncestors: worldDetails.hasAncestors, + hasEntities: worldDetails.hasEntities, }; } return stats; diff --git a/platform/mv3/scriptlets/css-procedural.template.js b/platform/mv3/extension/js/offscreen/make-utils.js similarity index 63% rename from platform/mv3/scriptlets/css-procedural.template.js rename to platform/mv3/extension/js/offscreen/make-utils.js index 0aaf6c67f1d7a..d5a67dc775f4e 100644 --- a/platform/mv3/scriptlets/css-procedural.template.js +++ b/platform/mv3/extension/js/offscreen/make-utils.js @@ -1,7 +1,7 @@ /******************************************************************************* - uBlock Origin Lite - a comprehensive, MV3-compliant content blocker - Copyright (C) 2014-present Raymond Hill + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2022-present Raymond Hill This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,19 +19,14 @@ Home: https://github.com/gorhill/uBlock */ -// Important! -// Isolate from global scope -(function uBOL_cssProceduralImport() { - -/******************************************************************************/ - -const rulesetId = self.$rulesetId$; - -self.proceduralImports = self.proceduralImports || []; -self.proceduralImports.push(rulesetId); - /******************************************************************************/ -})(); +export function hostnameCompare(a, b) { + const d = a.length - b.length; + if ( d !== 0 ) { return d; } + return a < b ? -1 : 1; +} -/******************************************************************************/ +export function isHnRegexOrPath(hn) { + return hn.includes('/'); +} diff --git a/platform/mv3/extension/js/safe-replace.js b/platform/mv3/extension/js/offscreen/safe-replace.js similarity index 100% rename from platform/mv3/extension/js/safe-replace.js rename to platform/mv3/extension/js/offscreen/safe-replace.js diff --git a/platform/mv3/extension/js/scriptlet.template.js b/platform/mv3/extension/js/offscreen/scriptlet.template.js similarity index 58% rename from platform/mv3/extension/js/scriptlet.template.js rename to platform/mv3/extension/js/offscreen/scriptlet.template.js index 6655d3ca9b211..c912752ed2a5b 100644 --- a/platform/mv3/extension/js/scriptlet.template.js +++ b/platform/mv3/extension/js/offscreen/scriptlet.template.js @@ -36,18 +36,7 @@ self.$scriptletCode$ const scriptletGlobals = {}; // eslint-disable-line -const $scriptletFunctions$ = self.$scriptletFunctions$; - -const $scriptletArgs$ = self.$scriptletArgs$; - -const $scriptletArglists$ = self.$scriptletArglists$; - -const $scriptletArglistRefs$ = self.$scriptletArglistRefs$; - -const $scriptletHostnames$ = self.$scriptletHostnames$; - -const $scriptletFromRegexes$ = self.$scriptletFromRegexes$; - +const $hasHostnames$ = self.$hasHostnames$; const $hasEntities$ = self.$hasEntities$; const $hasAncestors$ = self.$hasAncestors$; const $hasRegexes$ = self.$hasRegexes$; @@ -66,18 +55,22 @@ const entries = (( ) => { const hn1 = origin.slice(beg+3) const end = hn1.indexOf(':'); const hn2 = end === -1 ? hn1 : hn1.slice(0, end); - const hnParts = hn2.split('.'); if ( hn2.length === 0 ) { return; } - const hns = []; - for ( let i = 0; i < hnParts.length; i++ ) { - hns.push(`${hnParts.slice(i).join('.')}`); + const hns = [ hn2 ]; + for ( let pos = 0; ; ) { + pos = hn2.indexOf('.', pos) + 1; + if ( pos === 0 ) { break; } + hns.push(hn2.slice(pos)); } + hns.push('*'); const ens = []; if ( $hasEntities$ ) { - const n = hnParts.length - 1; - for ( let i = 0; i < n; i++ ) { - for ( let j = n; j > i; j-- ) { - ens.push(`${hnParts.slice(i,j).join('.')}.*`); + for ( let hn of hns ) { + for (;;) { + const pos = hn.lastIndexOf('.'); + if ( pos === -1 ) { break; } + hn = hn.slice(0, pos); + ens.push(`${hn}.*`); } } ens.sort((a, b) => { @@ -87,67 +80,70 @@ const entries = (( ) => { }); } return { hns, ens, i }; - }).filter(a => a !== undefined); + }).filter(a => a); })(); if ( entries.length === 0 ) { return; } -const collectArglistRefIndices = (out, hn, r) => { - let l = 0, i = 0, d = 0; - let candidate = ''; - while ( l < r ) { - i = l + r >>> 1; - candidate = $scriptletHostnames$[i]; - d = hn.length - candidate.length; - if ( d === 0 ) { - if ( hn === candidate ) { - out.add(i); break; +const todo = new Set(); + +if ( $hasHostnames$ ) { + const $scriptletHostnames$ = self.$scriptletHostnames$; + const collectArglistRefIndices = (out, hn, r) => { + let l = 0, i = 0, d = 0; + let candidate = ''; + while ( l < r ) { + i = l + r >>> 1; + candidate = $scriptletHostnames$[i]; + d = hn.length - candidate.length; + if ( d === 0 ) { + if ( hn === candidate ) { + out.add(i); break; + } + d = hn < candidate ? -1 : 1; + } + if ( d < 0 ) { + r = i; + } else { + l = i + 1; } - d = hn < candidate ? -1 : 1; - } - if ( d < 0 ) { - r = i; - } else { - l = i + 1; } - } - return i; -}; - -const indicesFromHostname = (out, hnDetails, suffix = '') => { - if ( hnDetails.hns.length === 0 ) { return; } - let r = $scriptletHostnames$.length; - for ( const hn of hnDetails.hns ) { - r = collectArglistRefIndices(out, `${hn}${suffix}`, r); - } - if ( $hasEntities$ ) { + return i + 1; + }; + const indicesFromHostname = (out, hnDetails, suffix = '') => { + if ( hnDetails.hns.length === 0 ) { return; } let r = $scriptletHostnames$.length; - for ( const en of hnDetails.ens ) { - r = collectArglistRefIndices(out, `${en}${suffix}`, r); + for ( const hn of hnDetails.hns ) { + r = collectArglistRefIndices(out, `${hn}${suffix}`, r); + } + if ( $hasEntities$ ) { + let r = $scriptletHostnames$.length; + for ( const en of hnDetails.ens ) { + r = collectArglistRefIndices(out, `${en}${suffix}`, r); + } + } + }; + const todoIndices = new Set(); + indicesFromHostname(todoIndices, entries[0]); + if ( $hasAncestors$ ) { + for ( const entry of entries ) { + if ( entry.i === 0 ) { continue; } + indicesFromHostname(todoIndices, entry, '>>'); } } -}; - -const todoIndices = new Set(); -indicesFromHostname(todoIndices, entries[0]); -if ( $hasAncestors$ ) { - for ( const entry of entries ) { - if ( entry.i === 0 ) { continue; } - indicesFromHostname(todoIndices, entry, '>>'); - } -} -$scriptletHostnames$.length = 0; - -// Collect arglist references -const todo = new Set(); -if ( todoIndices.size !== 0 ) { - const arglistRefs = $scriptletArglistRefs$.split(';'); - for ( const i of todoIndices ) { - for ( const ref of JSON.parse(`[${arglistRefs[i]}]`) ) { - todo.add(ref); + // Collect arglist references + if ( todoIndices.size ) { + const $scriptletArglistRefs$ = self.$scriptletArglistRefs$; + const arglistRefs = $scriptletArglistRefs$.split(';'); + for ( const i of todoIndices ) { + for ( const ref of JSON.parse(`[${arglistRefs[i]}]`) ) { + todo.add(ref); + } } } } + if ( $hasRegexes$ ) { + const $scriptletFromRegexes$ = self.$scriptletFromRegexes$; const { hns } = entries[0]; for ( let i = 0, n = $scriptletFromRegexes$.length; i < n; i += 3 ) { const needle = $scriptletFromRegexes$[i+0]; @@ -164,10 +160,12 @@ if ( $hasRegexes$ ) { } } } -if ( todo.size === 0 ) { return; } -// Execute scriplets -{ +// Execute scriptlets +if ( todo.size && todo.has(0) === false ) { + const $scriptletFunctions$ = self.$scriptletFunctions$; + const $scriptletArgs$ = self.$scriptletArgs$; + const $scriptletArglists$ = self.$scriptletArglists$; const arglists = $scriptletArglists$.split(';'); const args = $scriptletArgs$; for ( const ref of todo ) { diff --git a/platform/mv3/extension/js/prevent-popup.js b/platform/mv3/extension/js/prevent-popup.js index 3dd8ca650b3d5..a2317b15557b0 100644 --- a/platform/mv3/extension/js/prevent-popup.js +++ b/platform/mv3/extension/js/prevent-popup.js @@ -19,6 +19,7 @@ Home: https://github.com/gorhill/uBlock */ +import { rulesetConfig, saveRulesetConfig } from './config.js'; import { matchesFromHostnames } from './utils.js'; /******************************************************************************/ @@ -26,6 +27,7 @@ import { matchesFromHostnames } from './utils.js'; // https://github.com/uBlockOrigin/uBOL-home/issues/632 export async function registerPreventPopup(context) { + if ( rulesetConfig.popupBlockMode !== true ) { return; } const js = []; for ( const { id, popups } of context.rulesetsDetails ) { if ( popups === undefined ) { continue; } @@ -40,11 +42,11 @@ export async function registerPreventPopup(context) { const { none, basic, optimal, complete } = context.filteringModeDetails; let matches = []; let excludeMatches = []; - if ( complete.has('all-urls') ) { + if ( complete.has('all-urls') || optimal.has('all-urls') ) { matches = [ '*' ]; - excludeMatches = [ ...none, ...basic, ...optimal ]; + excludeMatches = [ ...none, ...basic ]; } else { - matches = [ ...complete ]; + matches = [ ...complete, ...optimal ]; } if ( matches.length === 0 ) { return; } @@ -57,3 +59,14 @@ export async function registerPreventPopup(context) { }; context.toAdd.push(directive); } + +/******************************************************************************/ + +export async function setPopupBlockMode(state, force = false) { + const newState = Boolean(state); + if ( force === false ) { + if ( newState === rulesetConfig.popupBlockMode ) { return; } + } + rulesetConfig.popupBlockMode = state; + await saveRulesetConfig(); +} diff --git a/platform/mv3/extension/js/report.js b/platform/mv3/extension/js/report.js index 66fa73f32f3e4..0fefde30c54b7 100644 --- a/platform/mv3/extension/js/report.js +++ b/platform/mv3/extension/js/report.js @@ -83,9 +83,9 @@ async function reportSpecificFilterIssue() { githubURL.searchParams.set('category', issueType); const configBody = [ - '```yaml', + '
\n\n```yaml', qs$('[data-i18n="supportS5H"] + pre').textContent, - '```', + '```\n
', '', ].join('\n'); githubURL.searchParams.set('configuration', configBody); diff --git a/platform/mv3/extension/js/ro-dnr-editor.js b/platform/mv3/extension/js/ro-dnr-editor.js index 609fd5a607a5a..221ce9f25ba20 100644 --- a/platform/mv3/extension/js/ro-dnr-editor.js +++ b/platform/mv3/extension/js/ro-dnr-editor.js @@ -19,10 +19,11 @@ Home: https://github.com/gorhill/uBlock */ -import { runtime, sendMessage } from './ext.js'; import { DNREditor } from './dnr-editor.js'; +import { deserialize } from '../lib/s14e-serializer.js'; import { i18n$ } from './i18n.js'; import { normalizeDNRRules } from './ext-compat.js'; +import { sendMessage } from './ext.js'; import { textFromRules } from './dnr-parser.js'; /******************************************************************************/ @@ -30,15 +31,17 @@ import { textFromRules } from './dnr-parser.js'; export class ReadOnlyDNREditor extends DNREditor { async getText(hint) { if ( hint === 'dnr.ro.dynamic' ) { - const rules = await sendMessage({ what: 'getEffectiveDynamicRules' }); + const rules = await sendMessage({ what: 'getAllDynamicRules' }); if ( Array.isArray(rules) === false ) { return; } + rules.sort((a, b) => a.id - b.id); this.id = 'dynamic'; this.count = rules.length; return textFromRules(rules, { keepId: true }); } if ( hint === 'dnr.ro.session' ) { - const rules = await sendMessage({ what: 'getEffectiveSessionRules' }); + const rules = await sendMessage({ what: 'getAllSessionRules' }); if ( Array.isArray(rules) === false ) { return; } + rules.sort((a, b) => a.id - b.id); this.id = 'session'; this.count = rules.length; return textFromRules(rules, { keepId: true }); @@ -46,40 +49,12 @@ export class ReadOnlyDNREditor extends DNREditor { const match = /^dnr\.ro\.(.+)$/.exec(hint); if ( match === null ) { return; } this.id = match[1]; - const allRulesetDetails = await sendMessage({ what: 'getRulesetDetails' }); - const rulesetDetails = allRulesetDetails.find(a => a.id === this.id); - if ( rulesetDetails === undefined ) { return; } - const manifestRulesets = runtime.getManifest().declarative_net_request.rule_resources; - const mainPathMap = new Map( - manifestRulesets.map(({ id, path }) => [ id, path ]) - ); - const realms = { - plain: 'main', - regex: 'regex', - }; - const promises = []; - for ( const [ realm, dir ] of Object.entries(realms) ) { - if ( Boolean(rulesetDetails.rules?.[realm]) === false ) { continue; } - const url = dir === 'main' - ? mainPathMap.get(this.id) - : `./rulesets/${dir}/${this.id}.json`; - promises.push( - fetch(url).then(response => - response.json() - ).then(rules => - normalizeDNRRules(rules) - ) - ); - } - const parts = await Promise.all(promises); - const allRules = []; - for ( const rules of parts ) { - for ( const rule of rules ) { - allRules.push(rule); - } - } - this.count = allRules.length; - return textFromRules(allRules, { keepId: true }); + const result = await sendMessage({ what: 'getRulesetRules', id: this.id }) || {}; + const allRules = result.serialized + ? deserialize(result.serialized).dnrRules ?? {} + : result.rules ?? {}; + this.count = allRules.length ?? 0; + return textFromRules(normalizeDNRRules(allRules), { keepId: true }); } on(editor) { diff --git a/platform/mv3/extension/js/ruleset-manager.js b/platform/mv3/extension/js/ruleset-manager.js index a0857a6ef0338..ea0db34ab9ed8 100644 --- a/platform/mv3/extension/js/ruleset-manager.js +++ b/platform/mv3/extension/js/ruleset-manager.js @@ -19,6 +19,13 @@ Home: https://github.com/gorhill/uBlock */ +import { + addImportedLists, + getEnabledImportedLists, + getImportedLists, + updateEnabledImportedLists, +} from './imported-lists.js'; + import { i18n, localRead, localRemove, localWrite, @@ -68,16 +75,17 @@ const isStrictBlockRule = rule => { /******************************************************************************/ -function getRulesetDetails() { - if ( getRulesetDetails.rulesetDetailsPromise !== undefined ) { - return getRulesetDetails.rulesetDetailsPromise; +export function getRulesetDetails() { + if ( getRulesetDetails.rulesetDetailsPromise === undefined ) { + getRulesetDetails.rulesetDetailsPromise = fetchJSON('/rulesets/ruleset-details'); } - getRulesetDetails.rulesetDetailsPromise = - fetchJSON('/rulesets/ruleset-details').then(entries => { - const rulesMap = new Map(entries.map(entry => [ entry.id, entry ])); - return rulesMap; - }); - return getRulesetDetails.rulesetDetailsPromise; + return Promise.all([ + getRulesetDetails.rulesetDetailsPromise, + getImportedLists(), + ]).then(results => { + const [ stock, imported ] = results; + return new Map(stock.concat(imported).map(entry => [ entry.id, entry ])); + }); } /******************************************************************************/ @@ -142,7 +150,7 @@ async function updateRegexRules(currentRules, addRules, removeRuleIds) { removeRuleIds.push(rule.id); } - const rulesetDetails = await getEnabledRulesetsDetails(); + const rulesetDetails = await getEnabledRulesetsDetails(true); // Fetch regexes for all enabled rulesets const toFetch = []; @@ -171,7 +179,26 @@ async function updateRegexRules(currentRules, addRules, removeRuleIds) { /******************************************************************************/ -async function updateDynamicRules() { +// https://github.com/uBlockOrigin/uBOL-home/issues/715 + +function toSafeDynamicRules(addRules) { + if ( Array.isArray(addRules) === false ) { return; } + if ( dnr.RuleConditionKeys?.TOP_DOMAINS ) { return addRules; } + const safeRules = []; + for ( const rule of addRules ) { + const { condition } = rule; + if ( condition.topDomains ) { continue; } + if ( condition.excludedTopDomains ) { + delete condition.excludedTopDomains; + } + safeRules.push(rule); + } + return safeRules; +} + +/******************************************************************************/ + +export async function updateDynamicAndSessionRules() { const currentRules = await dnr.getDynamicRules(); // Remove potentially left-over rules from previous version @@ -205,7 +232,10 @@ async function updateDynamicRules() { const response = {}; try { - await dnr.updateDynamicRules({ addRules, removeRuleIds }); + await dnr.updateDynamicRules({ + addRules: toSafeDynamicRules(addRules), + removeRuleIds, + }); if ( removeRuleIds.length !== 0 ) { ubolLog(`Remove ${removeRuleIds.length} dynamic DNR rules`); } @@ -213,7 +243,7 @@ async function updateDynamicRules() { ubolLog(`Add ${addRules.length} dynamic DNR rules`); } } catch(reason) { - ubolErr(`updateDynamicRules/${reason}`); + ubolErr(`updateDynamicAndSessionRules/${reason}`); response.error = `${reason}`; } @@ -227,18 +257,6 @@ async function updateDynamicRules() { /******************************************************************************/ -async function getEffectiveDynamicRules() { - const allRules = await dnr.getDynamicRules(); - const dynamicRules = []; - for ( const rule of allRules ) { - if ( rule.id >= USER_RULES_BASE_RULE_ID ) { continue; } - dynamicRules.push(rule); - } - return dynamicRules; -} - -/******************************************************************************/ - async function updateStrictBlockRules(currentRules, addRules, removeRuleIds) { // Remove existing strictblock-related rules for ( const rule of currentRules ) { @@ -260,7 +278,7 @@ async function updateStrictBlockRules(currentRules, addRules, removeRuleIds) { temporarilyExcluded = [], ] = await Promise.all([ hasBroadHostPermissions(), - getEnabledRulesetsDetails(), + getEnabledRulesetsDetails(true), localRead('excludedStrictBlockHostnames'), sessionRead('excludedStrictBlockHostnames'), ]); @@ -391,18 +409,6 @@ async function clearSessionRules() { /******************************************************************************/ -async function getEffectiveSessionRules() { - const allRules = await dnr.getSessionRules(); - const sessionRules = []; - for ( const rule of allRules ) { - if ( rule.id >= USER_RULES_BASE_RULE_ID ) { continue; } - sessionRules.push(rule); - } - return sessionRules; -} - -/******************************************************************************/ - async function filteringModesToDNR(modes) { const noneHostnames = new Set([ ...modes.none ]); const notNoneHostnames = new Set([ ...modes.basic, ...modes.optimal, ...modes.complete ]); @@ -456,6 +462,7 @@ export async function getDefaultRulesetsFromEnv() { const rulesetDetails = await getRulesetDetails(); const out = []; for ( const ruleset of rulesetDetails.values() ) { + if ( ruleset.group === 'imported' ) { continue; } const { id, enabled } = ruleset; if ( enabled ) { out.push(id); @@ -480,7 +487,7 @@ export async function getDefaultRulesetsFromEnv() { /******************************************************************************/ -async function patchDefaultRulesets() { +export async function patchDefaultRulesets() { const [ oldDefaultIds = [], newDefaultIds, @@ -488,21 +495,43 @@ async function patchDefaultRulesets() { ] = await Promise.all([ localRead('defaultRulesetIds'), getDefaultRulesetsFromEnv(), - getStaticRulesets().then(r => r.map(a => a.id)), + getStaticRulesets().then(a => a.map(a => a.id)), ]); const toAdd = []; const toRemove = []; + // New default rulesets to add for ( const id of newDefaultIds ) { if ( oldDefaultIds.includes(id) ) { continue; } toAdd.push(id); } + // Old default rulesets to remove for ( const id of oldDefaultIds ) { if ( newDefaultIds.includes(id) ) { continue; } toRemove.push(id); } + // Non-default rulesets removed from stock lists + const removedStockLists = new Map([ + [ 'dpollock-0', { + name: 'Dan Pollock’s hosts file', + url: 'https://someonewhocares.org/hosts/hosts', + homeURL: 'https://someonewhocares.org/hosts/', + }], + ]); + const reImported = /^[a-z]+:\/\//; + const importedToAdd = []; for ( const id of rulesetConfig.enabledRulesets ) { + if ( reImported.test(id) ) { continue; } if ( staticRulesetIds.includes(id) ) { continue; } + if ( toRemove.includes(id) ) { continue; } + if ( toAdd.includes(id) ) { continue; } toRemove.push(id); + if ( removedStockLists.has(id) ) { + importedToAdd.push(removedStockLists.get(id)); + } + } + if ( importedToAdd.length ) { + await addImportedLists(importedToAdd); + toAdd.push(...importedToAdd.map(a => a.url)); } localWrite('defaultRulesetIds', newDefaultIds); if ( toAdd.length === 0 && toRemove.length === 0 ) { return; } @@ -516,6 +545,63 @@ async function patchDefaultRulesets() { /******************************************************************************/ +export async function getEnabledRulesets() { + const [ + stockRulesets, + importedLists, + ] = await Promise.all([ + dnr.getEnabledRulesets(), + getEnabledImportedLists(), + ]); + return stockRulesets.concat(importedLists.map(a => a.id)); +} + +/******************************************************************************/ + +export async function getRulesetRules(id) { + const rulesetDetails = await getRulesetDetails(); + const ruleset = rulesetDetails.get(id); + if ( ruleset === undefined ) { return; } + if ( /^[a-z-]+:\/\//.test(id) ) { + const serialized = await localRead(`rulesets.imported.compiled.${id}`); + return { serialized }; + } + if ( Boolean(ruleset.rules) === false ) { return; } + const { total, regex } = ruleset.rules; + const promises = []; + if ( total !== regex ) { + promises.push(fetchJSON(`/rulesets/main/${id}`)); + } + if ( regex ) { + promises.push(fetchJSON(`/rulesets/regex/${id}`)); + } + const result = await Promise.all(promises); + return { rules: result.flat() }; +} + +/******************************************************************************/ + +async function updateEnabledRulesets(toEnable, toDisable, out) { + const reImported = /^[a-z-]+:\/\//; + const enableRulesetIds = toEnable.filter(a => reImported.test(a) === false); + const disableRulesetIds = toDisable.filter(a => reImported.test(a) === false); + if ( enableRulesetIds.length === 0 ) { + if ( disableRulesetIds.length === 0 ) { return false; } + } + return await dnr.updateEnabledRulesets({ + enableRulesetIds, + disableRulesetIds, + }).then(( ) => { + return true; + }).catch(reason => { + ubolErr(`updateEnabledRulesets/${reason}`); + out.error = `${reason}`; + return false; + }); +} + +/******************************************************************************/ + async function enableRulesets(ids) { const afterIds = new Set(ids); const [ @@ -523,7 +609,7 @@ async function enableRulesets(ids) { adminIds, rulesetDetails, ] = await Promise.all([ - dnr.getEnabledRulesets().then(ids => new Set(ids)), + getEnabledRulesets().then(ids => new Set(ids)), getAdminRulesets(), getRulesetDetails(), ]); @@ -549,18 +635,27 @@ async function enableRulesets(ids) { disableRulesetSet.add(id); } + const response = {}; + // Be sure the rulesets to enable/disable do exist in the current version, // otherwise the API throws. for ( const id of enableRulesetSet ) { if ( rulesetDetails.has(id) ) { continue; } enableRulesetSet.delete(id); + if ( /^[a-z-]+:\/\//.test(id) ) { + response.importedUpdated = true; + } else { + response.stockUpdated = true; + } } for ( const id of disableRulesetSet ) { if ( rulesetDetails.has(id) ) { continue; } disableRulesetSet.delete(id); } - if ( enableRulesetSet.size === 0 && disableRulesetSet.size === 0 ) { return; } + if ( enableRulesetSet.size === 0 && disableRulesetSet.size === 0 ) { + return response; + } const enableRulesetIds = Array.from(enableRulesetSet); const disableRulesetIds = Array.from(disableRulesetSet); @@ -572,22 +667,28 @@ async function enableRulesets(ids) { ubolLog(`Disable ruleset: ${disableRulesetIds}`); } - const response = {}; - - await dnr.updateEnabledRulesets({ + response.stockUpdated = await updateEnabledRulesets( enableRulesetIds, disableRulesetIds, - }).catch(reason => { - ubolErr(`updateEnabledRulesets/${reason}`); - response.error = `${reason}`; - }); + response, + ) || response.stockUpdated; + if ( response.stockUpdated ) { + const result = await updateDynamicAndSessionRules(); + if ( result?.error ) { + response.error ||= result.error; + } + response.changed = true; + } - const result = await updateDynamicRules(); - if ( result?.error ) { - response.error ||= result.error; + response.importedUpdated ||= await updateEnabledImportedLists( + enableRulesetIds, + disableRulesetIds + ); + if ( response.importedUpdated ) { + response.changed = true; } - await dnr.getEnabledRulesets().then(enabledRulesets => { + await getEnabledRulesets().then(enabledRulesets => { ubolLog(`Enabled rulesets: ${enabledRulesets}`); response.enabledRulesets = enabledRulesets; return dnr.getAvailableStaticRuleCount(); @@ -610,16 +711,18 @@ async function getStaticRulesets() { /******************************************************************************/ -async function getEnabledRulesetsDetails() { +async function getEnabledRulesetsDetails(stockOnly = false) { const [ - ids, + rulesetIds, rulesetDetails, ] = await Promise.all([ - dnr.getEnabledRulesets(), + getEnabledRulesets(), getRulesetDetails(), ]); + const reImported = /^[a-z-]+:\/\//; const out = []; - for ( const id of ids ) { + for ( const id of rulesetIds ) { + if ( stockOnly && reImported.test(id) ) { continue; } const ruleset = rulesetDetails.get(id); if ( ruleset === undefined ) { continue; } out.push(ruleset); @@ -643,9 +746,13 @@ async function updateUserRules() { const [ userRules, userRulesText = '', + sandboxRules, + importedRules, ] = await Promise.all([ getEffectiveUserRules(), localRead('userDnrRules'), + localRead('sandboxFilters.dnrRules'), + localRead('importedFilters.dnrRules'), ]); const effectiveRulesText = rulesetConfig.developerMode @@ -654,6 +761,16 @@ async function updateUserRules() { const parsed = rulesFromText(effectiveRulesText); const { rules } = parsed; + if ( Array.isArray(sandboxRules) ) { + sandboxRules.forEach(a => rules.push(a)); + } + // User rules have high priority + rules.forEach(a => { + a.priority = (a.priority || 1) + USER_RULES_PRIORITY; + }); + if ( Array.isArray(importedRules) ) { + importedRules.forEach(a => rules.push(a)); + } const removeRuleIds = [ ...userRules.map(a => a.id) ]; const rejectedRegexes = []; const addRules = await pruneInvalidRegexRules('user', rules, rejectedRegexes); @@ -673,7 +790,6 @@ async function updateUserRules() { let ruleId = 0; for ( const rule of addRules ) { rule.id = USER_RULES_BASE_RULE_ID + ruleId++; - rule.priority = (rule.priority || 1) + USER_RULES_PRIORITY; } // Rules are first removed separately to ensure registered rules match @@ -682,7 +798,7 @@ async function updateUserRules() { // adding rules. try { await dnr.updateDynamicRules({ removeRuleIds }); - await dnr.updateDynamicRules({ addRules }); + await dnr.updateDynamicRules({ addRules: toSafeDynamicRules(addRules) }); if ( removeRuleIds.length !== 0 ) { ubolLog(`updateUserRules() / Removed ${removeRuleIds.length} dynamic DNR rules`); } @@ -711,14 +827,9 @@ export { enableRulesets, excludeFromStrictBlock, filteringModesToDNR, - getEffectiveDynamicRules, - getEffectiveSessionRules, getEffectiveUserRules, getEnabledRulesetsDetails, - getRulesetDetails, - patchDefaultRulesets, setStrictBlockMode, - updateDynamicRules, updateSessionRules, updateUserRules, }; diff --git a/platform/mv3/extension/js/scripting-manager.js b/platform/mv3/extension/js/scripting-manager.js index c72bc193b95e3..e0b8aaec3a84c 100644 --- a/platform/mv3/extension/js/scripting-manager.js +++ b/platform/mv3/extension/js/scripting-manager.js @@ -24,18 +24,16 @@ import * as ut from './utils.js'; import { browser, localKeys, localRemove, localWrite, - sessionKeys, sessionRead, sessionRemove, sessionWrite, + sessionKeys, sessionRead, sessionRemove, + webextFlavor, } from './ext.js'; -import { - isUserScriptsAvailable, - registerCustomFilters, - registerCustomScriptlets, -} from './filter-manager.js'; import { ubolErr, ubolLog } from './debug.js'; import { fetchJSON } from './fetch.js'; import { getEnabledRulesetsDetails } from './ruleset-manager.js'; import { getFilteringModeDetails } from './mode-manager.js'; +import { registerCustomFilters } from './filter-manager.js'; +import { registerJob } from './alarms.js'; import { registerPreventPopup } from './prevent-popup.js'; import { registerToolbarIconToggler } from './action.js'; @@ -168,17 +166,19 @@ function registerGeneric(context, genericDetails) { /******************************************************************************/ -async function registerCosmetic(realm, context) { +async function registerCosmetic(context) { const { filteringModeDetails, rulesetsDetails } = context; { const keys = await localKeys(); - localRemove(keys.filter(a => a.startsWith(`css.${realm}.`))); + localRemove(keys.filter(a => a.startsWith('css.specific.'))); + // TODO: remove after a few versions after 2026.516.1652 + localRemove(keys.filter(a => a.startsWith('css.procedural.'))); } const rulesetIds = []; for ( const rulesetDetails of rulesetsDetails ) { - const count = rulesetDetails.css?.[realm] || 0; + const count = rulesetDetails.css?.specific ?? 0; if ( count === 0 ) { continue; } rulesetIds.push(rulesetDetails.id); } @@ -195,8 +195,8 @@ async function registerCosmetic(realm, context) { const promises = []; for ( const id of rulesetIds ) { promises.push( - fetchJSON(`/rulesets/scripting/${realm}/${id}`).then(data => { - return localWrite(`css.${realm}.${id}`, data); + fetchJSON(`/rulesets/scripting/specific/${id}`).then(data => { + return localWrite(`css.specific.${id}`, data); }) ); } @@ -205,10 +205,12 @@ async function registerCosmetic(realm, context) { normalizeMatches(matches); - const realmid = `css-${realm}`; - const js = rulesetIds.map(id => `/rulesets/scripting/${realm}/${id}.js`); + const js = rulesetIds.map(id => `/rulesets/scripting/specific/${id}.js`); js.unshift('/js/scripting/css-api.js', '/js/scripting/isolated-api.js'); - js.push(`/js/scripting/${realmid}.js`); + if ( webextFlavor === 'safari' ) { + js.push('/js/scripting/css-procedural-api.js'); + } + js.push('/js/scripting/css-specific.js'); const excludeMatches = []; if ( none.has('all-urls') === false && basic.has('all-urls') === false ) { @@ -222,7 +224,7 @@ async function registerCosmetic(realm, context) { } const directive = { - id: realmid, + id: 'css-specific', js, matches, allFrames: true, @@ -305,15 +307,15 @@ function registerScriptlet(context, scriptletDetails) { // Issue: Safari appears to completely ignore excludeMatches // https://github.com/radiolondra/ExcludeMatches-Test -export async function registerInjectables() { +export async function registerContentScripts() { if ( browser.scripting === undefined ) { return false; } - registerInjectables.pendingOp = - registerInjectables.pendingOp.then(( ) => registerInjectables.register()); - return registerInjectables.pendingOp; + registerContentScripts.pendingOp = + registerContentScripts.pendingOp.then(( ) => registerContentScripts.register()); + return registerContentScripts.pendingOp; } -registerInjectables.pendingOp = Promise.resolve(); +registerContentScripts.pendingOp = Promise.resolve(); -registerInjectables.register = async function register() { +registerContentScripts.register = async function register() { const [ filteringModeDetails, rulesetsDetails, @@ -321,7 +323,7 @@ registerInjectables.register = async function register() { genericDetails, ] = await Promise.all([ getFilteringModeDetails(), - getEnabledRulesetsDetails(), + getEnabledRulesetsDetails(true), getScriptletDetails(), getGenericDetails(), ]); @@ -334,11 +336,9 @@ registerInjectables.register = async function register() { await Promise.all([ registerScriptlet(context, scriptletDetails), - registerCosmetic('specific', context), - registerCosmetic('procedural', context), + registerCosmetic(context), registerGeneric(context, genericDetails), registerCustomFilters(context), - registerCustomScriptlets(context), registerPreventPopup(context), registerToolbarIconToggler(context), ]); @@ -359,7 +359,10 @@ registerInjectables.register = async function register() { } } - await resetCSSCache(); + await Promise.all([ + resetCSSCache(), + registerJob('pruneCSSCache', Date.now() + 15 * 60 * 1000), + ]); return true; }; @@ -367,23 +370,14 @@ registerInjectables.register = async function register() { /******************************************************************************/ export async function getRegisteredContentScripts() { - const promises = [ - browser.scripting.getRegisteredContentScripts(), - ]; - if ( isUserScriptsAvailable() ) { - promises.push(browser.userScripts.getScripts()); - } - const scripts = await Promise.all(promises).catch(( ) => []); - return scripts.flat().map(a => a.id); + const scripts = await browser.scripting.getRegisteredContentScripts(); + return scripts.map(a => a.id); } /******************************************************************************/ -export async function onWakeupRun() { - const cleanupTime = await sessionRead('scripting.manager.cleanup.time') || 0; - const now = Date.now(); - const since = now - cleanupTime; - if ( since < (15 * 60 * 1000) ) { return; } // 15 minutes +export async function pruneCSSCache() { + registerJob('pruneCSSCache', Date.now() + 15 * 60 * 1000); const MAX_CACHE_ENTRY_LOW = 256; const MAX_CACHE_ENTRY_HIGH = MAX_CACHE_ENTRY_LOW + Math.max(Math.round(MAX_CACHE_ENTRY_LOW / 8), 8); @@ -397,7 +391,6 @@ export async function onWakeupRun() { })); entries.sort((a, b) => b.t - a.t); sessionRemove(entries.slice(MAX_CACHE_ENTRY_LOW).map(a => a.key)); - sessionWrite('scripting.manager.cleanup.time', now) } /******************************************************************************/ diff --git a/platform/mv3/extension/js/scripting/css-generic.js b/platform/mv3/extension/js/scripting/css-generic.js index 472377623011b..5824fa655bfe0 100644 --- a/platform/mv3/extension/js/scripting/css-generic.js +++ b/platform/mv3/extension/js/scripting/css-generic.js @@ -253,7 +253,7 @@ for ( const entry of genericDetails ) { if ( i >= 0 ) { exceptions[i].split('\n').forEach(a => exceptionSet.add(a)); } else { - i = ~i; + i = ~i + 1; } } if ( entry.hasEntities ) { @@ -263,7 +263,7 @@ for ( const entry of genericDetails ) { if ( i >= 0 ) { exceptions[i].split('\n').forEach(a => exceptionSet.add(a)); } else { - i = ~i; + i = ~i + 1; } } } diff --git a/platform/mv3/extension/js/scripting/css-procedural-api.js b/platform/mv3/extension/js/scripting/css-procedural-api.js index 16c049de92667..040eafdc89540 100644 --- a/platform/mv3/extension/js/scripting/css-procedural-api.js +++ b/platform/mv3/extension/js/scripting/css-procedural-api.js @@ -29,6 +29,8 @@ if ( self.ProceduralFiltererAPI !== undefined ) { /******************************************************************************/ +const chrome = self.chrome ?? self.browser; + const nonVisualElements = { head: true, link: true, @@ -195,15 +197,23 @@ class PSelectorMatchesMediaTask extends PSelectorTask { class PSelectorMatchesPathTask extends PSelectorTask { constructor(filterer, task) { super(); + this.filterer = filterer; this.needle = regexFromString( task[1].replace(/\P{ASCII}/gu, s => encodeURIComponent(s)) ); + if ( PSelectorMatchesPathTask.#listener ) { return; } + PSelectorMatchesPathTask.#listener = true; + if ( Boolean(self.navigation) === false ) { return; } + self.navigation.addEventListener('navigate', ( ) => { + this.filterer.uBOL_DOMChanged(); + }); } transpose(node, output) { if ( this.needle.test(self.location.pathname + self.location.search) ) { output.push(node); } } + static #listener; } /******************************************************************************/ @@ -756,6 +766,7 @@ class ProceduralFilterer { self.ProceduralFiltererAPI = class { constructor() { + this.cssSheets = new Set(); this.proceduralFilterer = null; this.domObserver = null; } @@ -766,10 +777,18 @@ self.ProceduralFiltererAPI = class { this.domObserver.disconnect(); this.domObserver = null; } + const promises = []; if ( this.proceduralFilterer ) { - await this.proceduralFilterer.reset(); + promises.push(this.proceduralFilterer.reset()); this.proceduralFilterer = null; } + for ( const css of this.cssSheets ) { + promises.push( + chrome.runtime.sendMessage({ what: 'removeCSS', css }).catch(( ) => { }) + ); + } + this.cssSheets.clear(); + await Promise.all(promises); } addDeclaratives(selectors) { @@ -806,9 +825,11 @@ self.ProceduralFiltererAPI = class { if ( ruleText === undefined ) { continue; } sheetText.push(ruleText); } - if ( sheetText.length !== 0 ) { - self.cssAPI.insert(sheetText.join('\n')); - } + if ( sheetText.length === 0 ) { return; } + const cssSheet = sheetText.join('\n'); + if ( this.cssSheets.has(cssSheet) ) { return; } + this.cssSheets.add(cssSheet); + self.cssAPI.insert(cssSheet); } addProcedurals(selectors) { @@ -827,6 +848,10 @@ self.ProceduralFiltererAPI = class { qsa(selector) { const o = JSON.parse(selector); + if ( o.cssable ) { + const selector = o.selector.replace(/::[a-z()-]+$/, ''); + return Array.from(document.querySelectorAll(selector)); + } const pselector = new PSelectorRoot(null, o); return pselector.exec(); } diff --git a/platform/mv3/extension/js/scripting/css-procedural.js b/platform/mv3/extension/js/scripting/css-procedural.js deleted file mode 100644 index 221f162e7a1af..0000000000000 --- a/platform/mv3/extension/js/scripting/css-procedural.js +++ /dev/null @@ -1,64 +0,0 @@ -/******************************************************************************* - - uBlock Origin Lite - a comprehensive, MV3-compliant content blocker - Copyright (C) 2014-present Raymond Hill - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see {http://www.gnu.org/licenses/}. - - Home: https://github.com/gorhill/uBlock -*/ - -// Important! -// Isolate from global scope -(async function uBOL_cssProcedural() { - -/******************************************************************************/ - -const proceduralImports = self.proceduralImports || []; -self.proceduralImports = undefined; - -/******************************************************************************/ - -const selectors = await self.cosmeticAPI.getSelectors('procedural', proceduralImports); -self.cosmeticAPI.release(); -if ( selectors.length === 0 ) { return; } - -proceduralImports.length = 0; - -if ( self.ProceduralFiltererAPI === undefined ) { - self.ProceduralFiltererAPI = chrome.runtime.sendMessage({ - what: 'injectCSSProceduralAPI' - }).catch(( ) => { - }); -} - -await self.ProceduralFiltererAPI; - -self.listsProceduralFiltererAPI = new self.ProceduralFiltererAPI(); - -const declaratives = selectors.filter(a => a.cssable); -if ( declaratives.length !== 0 ) { - self.listsProceduralFiltererAPI.addDeclaratives(declaratives); -} - -const procedurals = selectors.filter(a => !a.cssable); -if ( procedurals.length !== 0 ) { - self.listsProceduralFiltererAPI.addProcedurals(procedurals); -} - -/******************************************************************************/ - -})(); - -void 0; diff --git a/platform/mv3/extension/js/scripting/css-specific.js b/platform/mv3/extension/js/scripting/css-specific.js index 10de503f9bac7..c28930c739f40 100644 --- a/platform/mv3/extension/js/scripting/css-specific.js +++ b/platform/mv3/extension/js/scripting/css-specific.js @@ -30,10 +30,149 @@ self.specificImports = undefined; /******************************************************************************/ -const selectors = await self.cosmeticAPI.getSelectors('specific', specificImports); -self.cosmeticAPI.release(); -if ( selectors.length === 0 ) { return; } -self.cssAPI.insert(`${selectors.join(',\n')}{display:none!important;}`); +const { isolatedAPI } = self; + +const sessionRead = async function(key) { + try { + const bin = await chrome.storage.session.get(key); + return bin?.[key] ?? undefined; + } catch { + } +}; + +const sessionWrite = function(key, data) { + try { + chrome.storage.session.set({ [key]: data }); + } catch { + } +}; + +const localRead = async function(key) { + try { + const bin = await chrome.storage.local.get(key); + return bin?.[key] ?? undefined; + } catch { + } +}; + +const selectorsFromListIndex = (data, ilist) => { + const list = JSON.parse(`[${data.selectorLists[ilist]}]`); + const { result } = data; + for ( const iselector of list ) { + if ( iselector >= 0 ) { + result.selectors.add(data.selectors[iselector]); + } else { + result.exceptions.add(data.selectors[~iselector]); + } + } +}; + +const selectorsFromHostnames = (haystack, needles, data) => { + let listref = -1; + for ( const needle of needles ) { + listref = isolatedAPI.binarySearch(haystack, needle, listref); + if ( listref >= 0 ) { + selectorsFromListIndex(data, data.selectorListRefs[listref]); + } else { + listref = ~listref + 1; + } + } +}; + +const selectorsFromRuleset = async (rulesetId, result) => { + const data = await localRead(`css.specific.${rulesetId}`); + if ( typeof data !== 'object' || data === null ) { return; } + data.result = result; + const { hostnames, regexes } = data; + if ( hostnames.length ) { + selectorsFromHostnames(hostnames, isolatedAPI.contexts.hostnames, data); + if ( data.hasEntities ) { + selectorsFromHostnames(hostnames, isolatedAPI.contexts.entities, data); + } + } + for ( let i = 0, n = regexes.length; i < n; i += 3 ) { + if ( thisHostname.includes(regexes[i+0]) === false ) { continue; } + if ( typeof regexes[i+1] === 'string' ) { + regexes[i+1] = new RegExp(regexes[i+1]); + } + if ( regexes[i+1].test(thisHostname) === false ) { continue; } + selectorsFromListIndex(data, regexes[i+2]); + } +}; + +const fillCache = async function(rulesetIds) { + const selectors = new Set(); + const exceptions = new Set(); + const result = { selectors, exceptions }; + const [ filteringModeDetails ] = await Promise.all([ + localRead('filteringModeDetails'), + ...rulesetIds.map(a => selectorsFromRuleset(a, result)), + ]); + const skip = filteringModeDetails?.none.some(a => { + if ( topHostname.endsWith(a) === false ) { return false; } + const n = a.length; + return topHostname.length === n || topHostname.at(-n-1) === '.'; + }); + for ( const selector of exceptions ) { + selectors.delete(selector); + } + if ( skip ) { + selectors.clear(); + } + cacheEntry.s = []; + cacheEntry.p = []; + for ( const selector of selectors ) { + if ( selector.startsWith('{') ) { + cacheEntry.p.push(JSON.parse(selector)); + } else { + cacheEntry.s.push(selector); + } + } + return cacheEntry; +}; + +const topHostname = isolatedAPI.contexts.topHostname; +const thisHostname = document.location.hostname || ''; +const cachePath = topHostname !== thisHostname ? `${topHostname}/` : ''; +const cacheKey = `cache.css.${cachePath}${thisHostname}`; + +let cacheEntry = await sessionRead(cacheKey) ?? { t: 0 }; +if ( cacheEntry.t === 0 ) { + cacheEntry = await fillCache(specificImports); +} +const now = Math.round(Date.now() / (5 * 60000)); +const since = now - cacheEntry.t; +if ( since > 1 ) { + cacheEntry.t = now; + sessionWrite(cacheKey, cacheEntry); +} + +const { s, p } = cacheEntry; + +if ( s.length !== 0 ) { + self.cssAPI.insert(`${s.join(',\n')}{display:none!important;}`); +} + +if ( p.length === 0 ) { return; } + +if ( self.ProceduralFiltererAPI === undefined ) { + self.ProceduralFiltererAPI = chrome.runtime.sendMessage({ + what: 'injectCSSProceduralAPI' + }).catch(( ) => { + }); +} + +await self.ProceduralFiltererAPI; +self.listsProceduralFiltererAPI = new self.ProceduralFiltererAPI(); + +const declaratives = p.filter(a => a.cssable); +if ( declaratives.length !== 0 ) { + self.listsProceduralFiltererAPI.addDeclaratives(declaratives); +} +const procedurals = p.filter(a => !a.cssable); +if ( procedurals.length !== 0 ) { + self.listsProceduralFiltererAPI.addProcedurals(procedurals); +} /******************************************************************************/ diff --git a/platform/mv3/extension/js/scripting/isolated-api.js b/platform/mv3/extension/js/scripting/isolated-api.js index e8e8ea0ca219c..090ad415779f4 100644 --- a/platform/mv3/extension/js/scripting/isolated-api.js +++ b/platform/mv3/extension/js/scripting/isolated-api.js @@ -41,14 +41,18 @@ const hn1 = origin.slice(beg+3) const end = hn1.indexOf(':'); const hn2 = end === -1 ? hn1 : hn1.slice(0, end); - const hnParts = hn2.split('.'); if ( hn2.length === 0 ) { return; } - const hns = []; - for ( let i = 0; i < hnParts.length; i++ ) { - hns.push(`${hnParts.slice(i).join('.')}`); + const hns = [ hn2 ]; + for ( let pos = 0; ; ) { + pos = hn2.indexOf('.', pos) + 1; + if ( pos === 0 ) { break; } + hns.push(hn2.slice(pos)); } return { hns, i }; - }).filter(a => a !== undefined); + }).filter(a => a); + if ( this.entries.length ) { + this.entries[0].hns.push('*'); + } }, get topHostname() { if ( this.entries.length === 0 ) { this.compute(); } @@ -62,11 +66,12 @@ if ( this.entries.length === 0 ) { this.compute(); } if ( this.entries[0].ens === undefined ) { const ens = []; - const hnparts = this.entries[0].hns[0].split('.'); - const n = hnparts.length - 1; - for ( let i = 0; i < n; i++ ) { - for ( let j = n; j > i; j-- ) { - ens.push(`${hnparts.slice(i,j).join('.')}.*`); + for ( let hn of this.entries[0].hns ) { + for (;;) { + const pos = hn.lastIndexOf('.'); + if ( pos === -1 ) { break; } + hn = hn.slice(0, pos); + ens.push(`${hn}.*`); } } ens.sort((a, b) => { @@ -102,144 +107,6 @@ })(self.isolatedAPI); - -(api => { - if ( typeof api === 'object' ) { return; } - - const cosmeticAPI = self.cosmeticAPI = {}; - const { isolatedAPI } = self; - const topHostname = isolatedAPI.contexts.topHostname; - const thisHostname = document.location.hostname || ''; - - const sessionRead = async function(key) { - try { - const bin = await chrome.storage.session.get(key); - return bin?.[key] ?? undefined; - } catch { - } - }; - - const sessionWrite = function(key, data) { - try { - chrome.storage.session.set({ [key]: data }); - } catch { - } - }; - - const localRead = async function(key) { - try { - const bin = await chrome.storage.local.get(key); - return bin?.[key] ?? undefined; - } catch { - } - }; - - const selectorsFromListIndex = (data, ilist) => { - const list = JSON.parse(`[${data.selectorLists[ilist]}]`); - const { result } = data; - for ( const iselector of list ) { - if ( iselector >= 0 ) { - result.selectors.add(data.selectors[iselector]); - } else { - result.exceptions.add(data.selectors[~iselector]); - } - } - }; - - const selectorsFromHostnames = (haystack, needles, data) => { - let listref = -1; - for ( const needle of needles ) { - listref = isolatedAPI.binarySearch(haystack, needle, listref); - if ( listref >= 0 ) { - selectorsFromListIndex(data, data.selectorListRefs[listref]); - } else { - listref = ~listref; - } - } - }; - - const selectorsFromRuleset = async (realm, rulesetId, result) => { - const data = await localRead(`css.${realm}.${rulesetId}`); - if ( typeof data !== 'object' || data === null ) { return; } - data.result = result; - selectorsFromHostnames(data.hostnames, isolatedAPI.contexts.hostnames, data); - if ( data.hasEntities ) { - selectorsFromHostnames(data.hostnames, isolatedAPI.contexts.entities, data); - } - const { regexes } = data; - for ( let i = 0, n = regexes.length; i < n; i += 3 ) { - if ( thisHostname.includes(regexes[i+0]) === false ) { continue; } - if ( typeof regexes[i+1] === 'string' ) { - regexes[i+1] = new RegExp(regexes[i+1]); - } - if ( regexes[i+1].test(thisHostname) === false ) { continue; } - selectorsFromListIndex(data, regexes[i+2]); - } - }; - - const fillCache = async function(realm, rulesetIds) { - const selectors = new Set(); - const exceptions = new Set(); - const result = { selectors, exceptions }; - const [ filteringModeDetails ] = await Promise.all([ - localRead('filteringModeDetails'), - ...rulesetIds.map(a => selectorsFromRuleset(realm, a, result)), - ]); - const skip = filteringModeDetails?.none.some(a => { - if ( topHostname.endsWith(a) === false ) { return false; } - const n = a.length; - return topHostname.length === n || topHostname.at(-n-1) === '.'; - }); - for ( const selector of exceptions ) { - selectors.delete(selector); - } - if ( skip ) { - selectors.clear(); - } - cacheEntry[realm.charAt(0)] = Array.from(selectors).map(a => - a.startsWith('{') ? JSON.parse(a) : a - ); - }; - - const readCache = async ( ) => { - cacheEntry = await sessionRead(cacheKey) || {}; - }; - - const cacheKey = - `cache.css.${topHostname !== thisHostname ? `${topHostname}/` : ''}${thisHostname || ''}`; - let clientCount = 0; - let cacheEntry; - - cosmeticAPI.getSelectors = async function(realm, rulesetIds) { - clientCount += 1; - const slot = realm.charAt(0); - if ( cacheEntry === undefined ) { - cacheEntry = readCache(); - } - if ( cacheEntry instanceof Promise ) { - await cacheEntry; - } - if ( cacheEntry[slot] === undefined ) { - cacheEntry[slot] = fillCache(realm, rulesetIds); - } - if ( cacheEntry[slot] instanceof Promise ) { - await cacheEntry[slot]; - } - return cacheEntry[slot]; - }; - - cosmeticAPI.release = function() { - clientCount -= 1; - if ( clientCount !== 0 ) { return; } - self.cosmeticAPI = undefined; - const now = Math.round(Date.now() / 15000); - const since = now - (cacheEntry.t || 0); - if ( since <= 1 ) { return; } - cacheEntry.t = now; - sessionWrite(cacheKey, cacheEntry); - }; -})(self.cosmeticAPI); - /******************************************************************************/ -void 0; \ No newline at end of file +void 0; diff --git a/platform/mv3/extension/js/scripting/picker.js b/platform/mv3/extension/js/scripting/picker.js index 775e95f0ff9cc..5172d53ccaa60 100644 --- a/platform/mv3/extension/js/scripting/picker.js +++ b/platform/mv3/extension/js/scripting/picker.js @@ -238,34 +238,47 @@ const excludedSelectors = [ /******************************************************************************/ async function previewSelector(selector) { - if ( selector === previewedSelector ) { return; } - if ( previewedSelector !== '' ) { - if ( previewedSelector.startsWith('{') ) { + previewSelector.promise = previewSelector.promise.then(( ) => + previewSelector.commit(selector) + ); + return previewSelector.promise; +} + +previewSelector.commit = async function(selector) { + if ( selector === previewSelector.selector ) { return; } + if ( previewSelector.selector !== '' ) { + if ( previewSelector.selector.startsWith('{') ) { if ( self.pickerProceduralFilteringAPI ) { await self.pickerProceduralFilteringAPI.reset(); } } - if ( previewedCSS !== '' ) { - await ubolOverlay.sendMessage({ what: 'removeCSS', css: previewedCSS }); - previewedCSS = ''; + if ( previewSelector.css !== '' ) { + await ubolOverlay.sendMessage({ what: 'removeCSS', css: previewSelector.css }); + previewSelector.css = ''; } } - previewedSelector = selector || ''; + previewSelector.selector = selector || ''; if ( selector === '' ) { return; } if ( selector.startsWith('{') ) { if ( self.ProceduralFiltererAPI === undefined ) { return; } if ( self.pickerProceduralFilteringAPI === undefined ) { self.pickerProceduralFilteringAPI = new self.ProceduralFiltererAPI(); } - self.pickerProceduralFilteringAPI.addProcedurals([ JSON.parse(selector) ]); + const pselector = JSON.parse(selector); + if ( pselector.cssable ) { + self.pickerProceduralFilteringAPI.addDeclaratives([ pselector ]); + } else { + self.pickerProceduralFilteringAPI.addProcedurals([ pselector ]); + } return; } - previewedCSS = `${selector}{display:none!important;}`; - await ubolOverlay.sendMessage({ what: 'insertCSS', css: previewedCSS }); -} + previewSelector.css = `${selector}{display:none!important;}`; + await ubolOverlay.sendMessage({ what: 'insertCSS', css: previewSelector.css }); +}; -let previewedSelector = ''; -let previewedCSS = ''; +previewSelector.promise = Promise.resolve(); +previewSelector.selector = ''; +previewSelector.css = ''; /******************************************************************************/ diff --git a/platform/mv3/extension/js/scripting/prevent-popup.js b/platform/mv3/extension/js/scripting/prevent-popup.js index 7c8968410af34..c988c000e0d7b 100644 --- a/platform/mv3/extension/js/scripting/prevent-popup.js +++ b/platform/mv3/extension/js/scripting/prevent-popup.js @@ -35,7 +35,7 @@ a.slice(i).join('.') ); - const hostnameSearch = (hostnames, targets) => { + const hostnameSearch = hostnames => { let l = 0, i = 0, d = 0; let r = hostnames.length; let candidate; @@ -59,28 +59,33 @@ return -1; }; - const regexSearch = (regexes, target) => { + const regexSearch = regexes => { for ( let i = 0; i < regexes.length; i += 2 ) { - const key = regexes[i+0]; - if ( target.includes(key.slice(1)) === false ) { continue; } - const re = new RegExp(regexes[i+1], key.charAt(0).trimEnd()); - if ( re.test(target) ) { return i; } + if ( href.includes(regexes[i+0]) === false ) { continue; } + const entries = JSON.parse(regexes[i+1]); + for ( const entry of entries ) { + if ( entry.xto && hostnameSearch(entry.xto) ) { continue; } + if ( entry.to && hostnameSearch(entry.to) === -1 ) { continue; } + const re = new RegExp(entry.re, entry.f); + if ( re.test(href) === false ) { continue; } + return i; + } } return -1; } let shouldClose = false; for ( const { block } of preventPopupDetails ) { - if ( hostnameSearch(block.hostnames, targets) === -1 ) { - if ( regexSearch(block.regexes, href) === -1 ) { continue; } + if ( hostnameSearch(block.hostnames) === -1 ) { + if ( regexSearch(block.regexes) === -1 ) { continue; } } shouldClose = true; break; } if ( shouldClose === false ) { return; } for ( const { allow } of preventPopupDetails ) { - if ( hostnameSearch(allow.hostnames, targets) === -1 ) { - if ( regexSearch(allow.regexes, href) === -1 ) { continue; } + if ( hostnameSearch(allow.hostnames) === -1 ) { + if ( regexSearch(allow.regexes) === -1 ) { continue; } } shouldClose = false; break; diff --git a/platform/mv3/extension/js/settings.js b/platform/mv3/extension/js/settings.js index 51d9de498c8ca..a92e7d0611942 100644 --- a/platform/mv3/extension/js/settings.js +++ b/platform/mv3/extension/js/settings.js @@ -26,12 +26,8 @@ import { renderFilterLists } from './filter-lists.js'; /******************************************************************************/ -let cachedRulesetData = {}; - -/******************************************************************************/ - function renderAdminRules() { - const { disabledFeatures: forbid = [] } = cachedRulesetData; + const { disabledFeatures: forbid = [] } = self.cachedRulesetData; if ( forbid.length === 0 ) { return; } dom.body.dataset.forbid = forbid.join(' '); if ( forbid.includes('dashboard') ) { @@ -42,18 +38,19 @@ function renderAdminRules() { /******************************************************************************/ function renderWidgets() { - if ( cachedRulesetData.firstRun ) { + const data = self.cachedRulesetData; + if ( data.firstRun ) { dom.cl.add(dom.body, 'firstRun'); } renderDefaultMode(); - qs$('#autoReload input[type="checkbox"]').checked = cachedRulesetData.autoReload; + qs$('#autoReload input[type="checkbox"]').checked = data.autoReload; { const input = qs$('#showBlockedCount input[type="checkbox"]'); - if ( cachedRulesetData.canShowBlockedCount ) { - input.checked = cachedRulesetData.showBlockedCount; + if ( data.canShowBlockedCount ) { + input.checked = data.showBlockedCount; } else { input.checked = false; dom.attr(input, 'disabled', ''); @@ -62,14 +59,19 @@ function renderWidgets() { { const input = qs$('#strictBlockMode input[type="checkbox"]'); - const canStrictBlock = cachedRulesetData.hasOmnipotence; - input.checked = canStrictBlock && cachedRulesetData.strictBlockMode; + const canStrictBlock = data.hasOmnipotence; + input.checked = canStrictBlock && data.strictBlockMode; dom.attr(input, 'disabled', canStrictBlock ? null : ''); } { - const state = Boolean(cachedRulesetData.developerMode) && - cachedRulesetData.disabledFeatures?.includes('develop') !== true; + const input = qs$('#popupBlockMode input[type="checkbox"]'); + input.checked = data.popupBlockMode; + } + + { + const state = Boolean(data.developerMode) && + data.disabledFeatures?.includes('develop') !== true; dom.body.dataset.develop = `${state}`; dom.prop('#developerMode input[type="checkbox"]', 'checked', state); } @@ -78,7 +80,7 @@ function renderWidgets() { /******************************************************************************/ function renderDefaultMode() { - const defaultLevel = cachedRulesetData.defaultFilteringMode; + const defaultLevel = self.cachedRulesetData.defaultFilteringMode; if ( defaultLevel !== 0 ) { qs$(`.filteringModeCard input[type="radio"][value="${defaultLevel}"]`).checked = true; } else { @@ -91,6 +93,7 @@ function renderDefaultMode() { async function onFilteringModeChange(ev) { const input = ev.target; const newLevel = parseInt(input.value, 10); + const data = self.cachedRulesetData; switch ( newLevel ) { case 1: { @@ -98,7 +101,7 @@ async function onFilteringModeChange(ev) { what: 'setDefaultFilteringMode', level: newLevel, }); - cachedRulesetData.defaultFilteringMode = actualLevel; + data.defaultFilteringMode = actualLevel; break; } case 2: @@ -111,20 +114,18 @@ async function onFilteringModeChange(ev) { what: 'setDefaultFilteringMode', level: newLevel, }); - cachedRulesetData.defaultFilteringMode = actualLevel; - cachedRulesetData.hasOmnipotence = true; + data.defaultFilteringMode = actualLevel; + data.hasOmnipotence = true; } break; } default: break; } - renderFilterLists(cachedRulesetData); renderWidgets(); } -dom.on( - '#defaultFilteringMode', +dom.on('#defaultFilteringMode', 'change', '.filteringModeCard input[type="radio"]', ev => { onFilteringModeChange(ev); } @@ -134,7 +135,7 @@ dom.on( async function backupSettings() { const api = await import('./backup-restore.js'); - const data = await api.backupToObject(cachedRulesetData); + const data = await api.backupToObject(self.cachedRulesetData); if ( data instanceof Object === false ) { return; } const json = JSON.stringify(data, null, 2) + '\n'; const a = document.createElement('a'); @@ -213,21 +214,28 @@ dom.on('#strictBlockMode input[type="checkbox"]', 'change', ev => { }); }); +dom.on('#popupBlockMode input[type="checkbox"]', 'change', ev => { + sendMessage({ + what: 'setPopupBlockMode', + state: ev.target.checked, + }); +}); + dom.on('#developerMode input[type="checkbox"]', 'change', ev => { const state = ev.target.checked; sendMessage({ what: 'setDeveloperMode', state }); dom.body.dataset.develop = `${state}`; }); -dom.on('section[data-pane="settings"] [data-i18n="backupButton"]', 'click', ( ) => { +dom.on('section[data-pane="settings"] button:has([data-i18n="backupButton"])', 'click', ( ) => { backupSettings(); }); -dom.on('section[data-pane="settings"] [data-i18n="restoreButton"]', 'click', ( ) => { +dom.on('section[data-pane="settings"] button:has([data-i18n="restoreButton"])', 'click', ( ) => { restoreSettings(); }); -dom.on('section[data-pane="settings"] [data-i18n="resetToDefaultButton"]', 'click', ( ) => { +dom.on('section[data-pane="settings"] button:has([data-i18n="resetToDefaultButton"])', 'click', ( ) => { resetSettings(); }); @@ -241,8 +249,9 @@ function listen() { listen.onmessage = ev => { const message = ev.data; if ( message instanceof Object === false ) { return; } - const local = cachedRulesetData; + const local = self.cachedRulesetData; let render = false; + let renderLists = false; if ( message.hasOmnipotence !== undefined ) { if ( message.hasOmnipotence !== local.hasOmnipotence ) { @@ -279,6 +288,13 @@ listen.onmessage = ev => { } } + if ( message.popupBlockMode !== undefined ) { + if ( message.popupBlockMode !== local.popupBlockMode ) { + local.popupBlockMode = message.popupBlockMode; + render = true; + } + } + if ( message.developerMode !== undefined ) { if ( message.developerMode !== local.developerMode ) { local.developerMode = message.developerMode; @@ -289,30 +305,42 @@ listen.onmessage = ev => { if ( message.adminRulesets !== undefined ) { if ( hashFromIterable(message.adminRulesets) !== hashFromIterable(local.adminRulesets) ) { local.adminRulesets = message.adminRulesets; - render = true; + renderLists = true; } } if ( message.enabledRulesets !== undefined ) { local.enabledRulesets = message.enabledRulesets; - render = true; + renderLists = true; } - if ( render === false ) { return; } - renderFilterLists(cachedRulesetData); - renderWidgets(); + if ( render ) { + renderWidgets(); + } + if ( renderLists ) { + renderFilterLists(true); + } }; /******************************************************************************/ +self.cachedRulesetData = {}; + sendMessage({ what: 'getOptionsPageData', }).then(data => { if ( !data ) { return; } - cachedRulesetData = data; + self.cachedRulesetData = data; + const supports = [] + if ( data.supportsUserScripts ) { + supports.push('user-scripts'); + } + if ( data.supportsCompiledFilters ) { + supports.push('compiled-filters'); + } + dom.body.dataset.supports = supports.join(' '); try { renderAdminRules(); - renderFilterLists(cachedRulesetData); renderWidgets(); } catch(reason) { console.error(reason); diff --git a/platform/mv3/extension/js/strictblock.js b/platform/mv3/extension/js/strictblock.js index b083f4bfaa19a..57cff6268f033 100644 --- a/platform/mv3/extension/js/strictblock.js +++ b/platform/mv3/extension/js/strictblock.js @@ -35,11 +35,12 @@ function urlToFragment(raw) { try { const fragment = new DocumentFragment(); const url = new URL(raw); + const href = url.href; const hn = url.hostname; - const i = raw.indexOf(hn); + const i = href.indexOf(hn); const b = document.createElement('b'); b.append(hn); - fragment.append(raw.slice(0,i), b, raw.slice(i+hn.length)); + fragment.append(href.slice(0,i), b, href.slice(i+hn.length)); return fragment; } catch { } @@ -109,12 +110,11 @@ function fragmentFromTemplate(template, placeholder, text, details) { // Enforce popup filters (async ( ) => { - const filteringMode = await sendMessage({ - what: 'getFilteringMode', - hostname: toURL.hostname, + const currentConfig = await sendMessage({ + what: 'getCurrentConfig', }); // Enforce popup filtering in complete mode only - if ( filteringMode < 3 ) { return; } + if ( currentConfig.popupBlockingMode !== true ) { return; } const rulesetDetails = await rulesetDetailsPromise; const toImport = []; for ( const details of rulesetDetails ) { diff --git a/platform/mv3/extension/js/troubleshooting.js b/platform/mv3/extension/js/troubleshooting.js index 4129ebb38638c..d9332e1064b30 100644 --- a/platform/mv3/extension/js/troubleshooting.js +++ b/platform/mv3/extension/js/troubleshooting.js @@ -54,23 +54,23 @@ export async function getTroubleshootingInfo(details) { const [ platformInfo, defaultConfig, + currentConfig, enabledRulesets, rulesetDetails, defaultMode, userRules, consoleOutput, - showBlockedCount, registeredScripts, hasOmnipotence, ] = await Promise.all([ runtime.getPlatformInfo(), sendMessage({ what: 'getDefaultConfig' }), + sendMessage({ what: 'getCurrentConfig' }), sendMessage({ what: 'getEnabledRulesets' }), sendMessage({ what: 'getRulesetDetails' }).then(a => new Map(a.map(a => [ a.id, a ]))), sendMessage({ what: 'getDefaultFilteringMode' }), sendMessage({ what: 'getEffectiveUserRules' }), sendMessage({ what: 'getConsoleOutput' }), - sendMessage({ what: 'getShowBlockedCount' }), sendMessage({ what: 'getRegisteredContentScripts' }), sendMessage({ what: 'hasBroadHostPermissions' }), ]); @@ -113,9 +113,15 @@ export async function getTroubleshootingInfo(details) { filtering, permission: hasOmnipotence ? 'all' : 'ask', }; + if ( currentConfig.strictBlockMode !== defaultConfig.strictBlockMode ) { + config.strictblock = currentConfig.strictBlockMode; + } + if ( currentConfig.popupBlockMode !== defaultConfig.popupBlockMode ) { + config.popupblock = currentConfig.popupBlockMode; + } if ( details?.tabId ) { let badge = '?'; - if ( showBlockedCount ) { + if ( currentConfig.showBlockedCount ) { badge = await browser.action.getBadgeText({ tabId: details.tabId }); } if ( badge ) { diff --git a/platform/mv3/extension/js/ubo-parser.js b/platform/mv3/extension/js/ubo-parser.js index 9ab3059d71799..0e50e930cec93 100644 --- a/platform/mv3/extension/js/ubo-parser.js +++ b/platform/mv3/extension/js/ubo-parser.js @@ -25,7 +25,7 @@ import redirectResourceMap from './redirect-resources.js'; /******************************************************************************/ -const validResourceTypes = [ +const safeResourceTypes = [ 'main_frame', 'sub_frame', 'stylesheet', @@ -38,8 +38,6 @@ const validResourceTypes = [ 'csp_report', 'media', 'websocket', - 'webtransport', - 'webbundle', 'other', ]; @@ -118,27 +116,111 @@ function ownerFromPropertyPath(root, path) { /******************************************************************************/ -function mergeArrays(rules, propertyPath) { +function propertySorter(k, v) { + if ( k.startsWith('_') ) { return; } + if ( Array.isArray(v) ) { + return typeof v[0] === 'string' ? v.sort() : v; + } + if ( v instanceof Object ) { + const sorted = {}; + for ( const kk of Object.keys(v).sort() ) { + sorted[kk] = v[kk]; + } + return sorted; + } + return v; +} + +/******************************************************************************/ + +function mergeDomains(rules, includeProp, excludeProp) { + const out = []; + const distinctRules = new Map(); + for ( const rule of rules ) { + const { id } = rule; + if ( rule.condition === undefined ) { + out.push(rule); + continue; + } + const includes = rule.condition[includeProp]; + rule.condition[includeProp] = undefined; + const excludes = rule.condition[excludeProp]; + rule.condition[excludeProp] = undefined; + rule.id = undefined; + const hash = JSON.stringify(rule, propertySorter); + const details = distinctRules.get(hash) || { id }; + if ( details.initialized !== true ) { + details.initialized = true; + distinctRules.set(hash, details); + } + if ( Boolean(includes?.length) === false ) { + details.includes = []; + } else if ( details.includes === undefined ) { + details.includes = includes; + } else if ( details.includes.length ) { + for ( const hn of includes ) { + details.includes.push(hn); + } + } + if ( excludes?.length ) { + if ( details.excludes === undefined ) { + details.excludes = excludes; + } else { + for ( const hn of excludes ) { + details.excludes.push(hn); + } + } + } + } + for ( const [ hash, details ] of distinctRules ) { + const rule = JSON.parse(hash); + rule.id = details.id; + if ( details.includes?.length ) { + rule.condition[includeProp] = Array.from(new Set(details.includes)).sort(); + } + if ( details.excludes?.length ) { + rule.condition[excludeProp] = Array.from(new Set(details.excludes)).sort(); + } + out.push(rule); + } + return out; +} + +/******************************************************************************/ + +function mergeArrays(rules, propertyPath, emptyIsAll = false) { const out = []; const distinctRules = new Map(); for ( const rule of rules ) { const { id } = rule; const { owner, prop } = ownerFromPropertyPath(rule, propertyPath); - if ( owner === undefined || Array.isArray(owner[prop]) === false ) { + if ( owner === undefined ) { out.push(rule); continue; } - const collection = owner[prop] || []; + const collection = owner[prop]; + if ( Array.isArray(collection) === false || collection.length === 0 ) { + if ( emptyIsAll === false ) { + out.push(rule); + continue; + } + } owner[prop] = undefined; rule.id = undefined; - const hash = JSON.stringify(rule); - const details = distinctRules.get(hash) || - { id, collection: new Set() }; - if ( details.collection.size === 0 ) { + const hash = JSON.stringify(rule, propertySorter); + const details = distinctRules.get(hash) || { id }; + if ( details.initialized !== true ) { + details.initialized = true; distinctRules.set(hash, details); } - for ( const hn of collection ) { - details.collection.add(hn); + if ( Boolean(collection?.length) === false ) { + details.collection = []; + } else if ( details.collection === undefined ) { + details.collection = collection; + } else if ( details.collection.length ) { + for ( const v of collection ) { + details.collection.push(v); + } } } for ( const [ hash, { id, collection } ] of distinctRules ) { @@ -146,9 +228,9 @@ function mergeArrays(rules, propertyPath) { if ( id ) { rule.id = id; } - if ( collection.size !== 0 ) { + if ( collection?.length ) { const { owner, prop } = ownerFromPropertyPath(rule, propertyPath); - owner[prop] = Array.from(collection).sort(); + owner[prop] = Array.from(new Set(collection)).sort(); } out.push(rule); } @@ -157,24 +239,36 @@ function mergeArrays(rules, propertyPath) { /******************************************************************************/ -function minimizeRuleset(rules) { - rules = mergeArrays(rules, 'condition.requestDomains'); - rules = mergeArrays(rules, 'condition.excludedRequestDomains'); - rules = mergeArrays(rules, 'condition.initiatorDomains'); - rules = mergeArrays(rules, 'condition.excludedInitiatorDomains'); - rules = mergeArrays(rules, 'condition.topDomains'); - rules = mergeArrays(rules, 'condition.excludedTopDomains'); - rules = mergeArrays(rules, 'condition.resourceTypes'); - rules = mergeArrays(rules, 'condition.excludedRequestMethods'); - rules = mergeArrays(rules, 'condition.requestMethods'); - rules = mergeArrays(rules, 'condition.excludedResourceTypes'); +export function minimizeRuleset(rules) { + rules.forEach(rule => { + const { condition } = rule; + if ( condition.excludedResourceTypes ) { return; } + if ( condition.resourceTypes ) { return; } + if ( condition.urlFilter ) { return; } + if ( condition.regexFilter ) { return; } + condition.excludedResourceTypes = [ 'main_frame' ]; + }); + rules = mergeArrays(rules, 'action.responseHeaders'); rules = mergeArrays(rules, 'action.redirect.transform.queryTransform.removeParams'); + rules = mergeArrays(rules, 'condition.responseHeaders'); + rules = mergeArrays(rules, 'condition.resourceTypes', true); + rules = mergeArrays(rules, 'condition.requestMethods', true); + rules = mergeDomains(rules, 'initiatorDomains', 'excludedInitiatorDomains'); + rules = mergeDomains(rules, 'requestDomains', 'excludedRequestDomains'); + rules = mergeDomains(rules, 'topDomains', 'excludedTopDomains'); + rules.forEach(rule => { + const { condition } = rule; + if ( condition.resourceTypes ) { return; } + if ( condition.excludedResourceTypes?.length !== 1 ) { return; } + if ( condition.excludedResourceTypes[0] !== 'main_frame' ) { return; } + delete condition.excludedResourceTypes; + }); return rules; } /******************************************************************************/ -function minimizeRules(rules) { +export function minimizeRules(rules) { const hostnameListProp = [ 'requestDomains', 'excludedRequestDomains', @@ -215,7 +309,46 @@ function dropEntities(rule, prop) { /******************************************************************************/ -function validateRules(rules) { +function convertInitiatorDomainsToRequestDomains(rule) { + if ( rule.condition.initiatorDomains ) { + rule.condition.requestDomains ??= []; + rule.condition.requestDomains = [ + ...rule.condition.requestDomains, + ...rule.condition.initiatorDomains, + ]; + delete rule.condition.initiatorDomains; + } + if ( rule.condition.excludedInitiatorDomains ) { + rule.condition.excludedRequestDomains ??= []; + rule.condition.excludedRequestDomains = [ + ...rule.condition.excludedRequestDomains, + ...rule.condition.excludedInitiatorDomains, + ]; + delete rule.condition.excludedInitiatorDomains; + } +} + +/******************************************************************************/ + +// https://github.com/uBlockOrigin/uBOL-home/discussions/736 + +export function expandRemoveparamsRule(rule0, out) { + if ( Boolean(rule0.condition.resourceTypes?.includes('main_frame')) === false ) { return; } + if ( rule0.condition.initiatorDomains === undefined ) { return; } + if ( rule0.condition.resourceTypes.length === 1 ) { + convertInitiatorDomainsToRequestDomains(rule0); + return; + } + const rule1 = structuredClone(rule0); + rule0.condition.resourceTypes = rule0.condition.resourceTypes.filter(a => a !== 'main_frame'); + rule1.condition.resourceTypes = [ 'main_frame' ]; + convertInitiatorDomainsToRequestDomains(rule1); + out.push(rule1); +} + +/******************************************************************************/ + +export function validateRules(rules) { const out = []; for ( const rule of rules ) { const { condition } = rule; @@ -243,15 +376,26 @@ function validateRules(rules) { /******************************************************************************/ -export function parseNetworkFilter(parser) { +// Priority: +// Removeparam: 1-4 +// Block: 10 (default priority) +// Redirect: 11-19 +// Excepted redirect: 21-29 +// Allow: 30 +// Block important: 40 +// Redirect important: 41-49 + +export function parseNetworkFilter(parser, details = {}, out = []) { if ( parser.isNetworkFilter() === false ) { return; } if ( parser.hasError() ) { return; } + const validResourceTypes = details.resourceTypes ?? safeResourceTypes; const rule = { action: { type: 'block' }, condition: { }, }; - if ( parser.isException() ) { + const isException = parser.isException(); + if ( isException ) { rule.action.type = 'allow'; } @@ -275,12 +419,12 @@ export function parseNetworkFilter(parser) { } const defaultResourceTypes = new Set(); - let defaultUrlFilter = ''; - const initiatorDomains = new Set(); const excludedInitiatorDomains = new Set(); const requestDomains = new Set(); const excludedRequestDomains = new Set(); + const topDomains = new Set(); + const excludedTopDomains = new Set(); const requestMethods = new Set(); const excludedRequestMethods = new Set(); const resourceTypes = new Set(); @@ -298,7 +442,8 @@ export function parseNetworkFilter(parser) { } }; - let priority = 0; + let subpriority = 0; + let isImportant = false; for ( const type of parser.getNodeTypes() ) { switch ( type ) { @@ -389,6 +534,7 @@ export function parseNetworkFilter(parser) { } case sfp.NODE_TYPE_NET_OPTION_NAME_RESPONSEHEADER: { const details = sfp.parseHeaderValue(parser.getNetOptionValue(type)); + if ( details.bad ) { return; } const headerInfo = { header: details.name, }; @@ -396,14 +542,18 @@ export function parseNetworkFilter(parser) { if ( details.isRegex ) { return; } headerInfo.values = [ details.value ]; } - rule.condition.responseHeaders = [ headerInfo ]; + if ( details.not ) { + rule.condition.excludedResponseHeaders = [ headerInfo ]; + } else { + rule.condition.responseHeaders = [ headerInfo ]; + } break; } case sfp.NODE_TYPE_NET_OPTION_NAME_IMAGE: processResourceType('image', type); break; case sfp.NODE_TYPE_NET_OPTION_NAME_IMPORTANT: - priority += 30; + isImportant = true; break; case sfp.NODE_TYPE_NET_OPTION_NAME_MATCHCASE: rule.condition.isUrlFilterCaseSensitive = true; @@ -451,8 +601,7 @@ export function parseNetworkFilter(parser) { let value = parser.getNetOptionValue(type); const match = /:(\d+)$/.exec(value); if ( match ) { - const subpriority = parseInt(match[1], 10); - priority += Math.min(subpriority, 8); + subpriority = Math.min(parseInt(match[1], 10) || 0, 8); value = value.slice(0, match.index); } if ( validRedirectResources.has(value) === false ) { return; } @@ -460,7 +609,6 @@ export function parseNetworkFilter(parser) { rule.action.redirect = { extensionPath: `/web_accessible_resources/${validRedirectResources.get(value)}`, }; - priority += 11; break; } case sfp.NODE_TYPE_NET_OPTION_NAME_REMOVEPARAM: { @@ -471,6 +619,11 @@ export function parseNetworkFilter(parser) { const removeParams = []; if ( details.name ) { removeParams.push(details.name); + if ( rule.condition.urlFilter === undefined ) { + if ( rule.condition.regexFilter === undefined ) { + rule.condition.urlFilter = `^${details.name}=`; + } + } } rule.action.type = 'redirect'; rule.action.redirect = { @@ -479,7 +632,6 @@ export function parseNetworkFilter(parser) { defaultResourceTypes.add('main_frame'); defaultResourceTypes.add('sub_frame'); defaultResourceTypes.add('xmlhttprequest'); - defaultUrlFilter = '?'; break; } case sfp.NODE_TYPE_NET_OPTION_NAME_SCRIPT: @@ -501,6 +653,22 @@ export function parseNetworkFilter(parser) { } break; } + case sfp.NODE_TYPE_NET_OPTION_NAME_TOP: { + const { included, excluded } = parseHostnameList( + parser.getNetFilterTopOptionIterator() + ); + if ( included.good.length === 0 ) { + if ( included.bad.length !== 0 ) { return; } + } + if ( excluded.bad.length !== 0 ) { return; } + for ( const hn of included.good ) { + topDomains.add(hn); + } + for ( const hn of excluded.good ) { + excludedTopDomains.add(hn); + } + break; + } case sfp.NODE_TYPE_NET_OPTION_NAME_URLTRANSFORM: { const parsed = sfp.parseReplaceByRegexValue(parser.getNetOptionValue(type)); if ( parsed === undefined ) { return; } @@ -521,9 +689,6 @@ export function parseNetworkFilter(parser) { break; } } - if ( pattern === '*' && defaultUrlFilter !== '' ) { - rule.condition.urlFilter = defaultUrlFilter; - } if ( initiatorDomains.size !== 0 ) { rule.condition.initiatorDomains = Array.from(initiatorDomains).sort(); } @@ -536,6 +701,12 @@ export function parseNetworkFilter(parser) { if ( excludedRequestDomains.size !== 0 ) { rule.condition.excludedRequestDomains = Array.from(excludedRequestDomains).sort(); } + if ( topDomains.size !== 0 ) { + rule.condition.topDomains = Array.from(topDomains).sort(); + } + if ( excludedTopDomains.size !== 0 ) { + rule.condition.excludedTopDomains = Array.from(excludedTopDomains).sort(); + } if ( requestMethods.size !== 0 ) { rule.condition.requestMethods = Array.from(requestMethods).sort(); } @@ -552,17 +723,49 @@ export function parseNetworkFilter(parser) { } if ( excludedResourceTypes.size !== 0 ) { if ( resourceTypes.size !== 0 ) { return; } + excludedResourceTypes.add('main_frame'); rule.condition.excludedResourceTypes = Array.from(excludedResourceTypes).sort(); } - if ( priority !== 0 ) { + let priority = 1; + if ( rule.action.type === 'block' ) { + priority = isImportant ? 40 : 10; + } else if ( rule.action.type === 'allow' ) { + priority = 30; + } else if ( rule.action.type === 'redirect' ) { + if ( rule.action.redirect.extensionPath ) { + if ( isException ) { + rule.action.type = 'block'; + delete rule.action.redirect; + priority = 20; + } else { + priority = (isImportant ? 41 : 11) + subpriority; + } + } else if ( rule.action.redirect.transform?.queryTransform?.removeParams ) { + if ( isException ) { + rule.action.type = 'allow'; + delete rule.action.redirect; + } + } else if ( rule.action.redirect.regexSubstitution ) { + } + } else if ( rule.action.type === 'modifyHeaders' ) { + if ( isException ) { + rule.action.type = 'allow'; + delete rule.action.responseHeaders; + } + } + if ( priority !== 1 ) { rule.priority = priority; } - return rule; + out.push(rule); + if ( rule.action.redirect?.transform?.queryTransform?.removeParams ) { + expandRemoveparamsRule(rule, out); + } + return out; } /******************************************************************************/ -export function parseFilters(text) { +export function parseFilters(text, details) { if ( text.startsWith('---') ) { return; } if ( text.endsWith('---') ) { return; } const lines = text.split(/\n/); @@ -572,9 +775,7 @@ export function parseFilters(text) { for ( const line of lines ) { parser.parse(line); if ( parser.isNetworkFilter() === false ) { continue; } - const rule = parseNetworkFilter(parser); - if ( rule === undefined ) { continue; } - rules.push(rule); + parseNetworkFilter(parser, details, rules); } rules = minimizeRuleset(rules); rules = minimizeRules(rules); diff --git a/platform/mv3/extension/js/utils.js b/platform/mv3/extension/js/utils.js index 2fdd02eead032..98a77d63a349e 100644 --- a/platform/mv3/extension/js/utils.js +++ b/platform/mv3/extension/js/utils.js @@ -21,7 +21,7 @@ /******************************************************************************/ -function parsedURLromOrigin(origin) { +export function parsedURLromOrigin(origin) { try { return new URL(origin); } catch { @@ -30,7 +30,7 @@ function parsedURLromOrigin(origin) { /******************************************************************************/ -const toBroaderHostname = hn => { +export const toBroaderHostname = hn => { if ( hn === '*' ) { return ''; } const pos = hn.indexOf('.'); return pos !== -1 ? hn.slice(pos+1) : '*'; @@ -40,7 +40,7 @@ const toBroaderHostname = hn => { // Is hna descendant hostname of hnb? -const isDescendantHostname = (hna, hnb) => { +export const isDescendantHostname = (hna, hnb) => { if ( hnb === 'all-urls' ) { return true; } if ( hna.endsWith(hnb) === false ) { return false; } if ( hna === hnb ) { return false; } @@ -54,7 +54,7 @@ const isDescendantHostname = (hna, hnb) => { * @param iterb - an iterable representing the haystack of hostnames. */ -const isDescendantHostnameOfIter = (hna, iterb) => { +export const isDescendantHostnameOfIter = (hna, iterb) => { const setb = iterb instanceof Set ? iterb : new Set(iterb); if ( setb.has('all-urls') || setb.has('*') ) { return true; } let hn = hna; @@ -74,7 +74,7 @@ const isDescendantHostnameOfIter = (hna, iterb) => { * @param iterb - an iterable which hostnames must be matched. */ -const intersectHostnameIters = (itera, iterb) => { +export const intersectHostnameIters = (itera, iterb) => { const setb = iterb instanceof Set ? iterb : new Set(iterb); if ( setb.has('all-urls') || setb.has('*') ) { return Array.from(itera); } const out = []; @@ -86,7 +86,7 @@ const intersectHostnameIters = (itera, iterb) => { return out; }; -const subtractHostnameIters = (itera, iterb) => { +export const subtractHostnameIters = (itera, iterb) => { const setb = iterb instanceof Set ? iterb : new Set(iterb); if ( setb.has('all-urls') || setb.has('*') ) { return []; } const out = []; @@ -130,56 +130,13 @@ export const hostnamesFromMatches = origins => { /******************************************************************************/ -export const deepEquals = (a, b) => { - switch ( typeof a ) { - case 'undefined': - case 'boolean': - case 'number': - case 'string': - return a === b; - } - // case 'object': - if ( typeof b !== 'object' ) { return false; } - if ( a === null || b === null ) { return a === b; } - if ( Array.isArray(a) || Array.isArray(b) ) { - if ( Array.isArray(a) === false || Array.isArray(b) === false ) { return false; } - if ( a.length !== b.length ) { return false; } - for ( let i = 0; i < a.length; i++ ) { - if ( deepEquals(a[i], b[i]) === false ) { return false; } - } - return true; - } - const akeys = Object.keys(a); - const bkeys = Object.keys(b); - if ( akeys.length !== bkeys.length ) { return false; } - for ( const k of akeys ) { - if ( deepEquals(a[k], b[k]) === false ) { return false; } - } - return true; -}; - -/******************************************************************************/ - -const broadcastMessage = message => { +export const broadcastMessage = message => { const bc = new self.BroadcastChannel('uBOL'); bc.postMessage(message); }; /******************************************************************************/ -// Important: We need to sort the arrays for fast comparison -const strArrayEq = (a = [], b = [], sort = true) => { - const alen = a.length; - if ( alen !== b.length ) { return false; } - if ( sort ) { a.sort(); b.sort(); } - for ( let i = 0; i < alen; i++ ) { - if ( a[i] !== b[i] ) { return false; } - } - return true; -}; - -/******************************************************************************/ - // The goal is just to be able to find out whether a specific version is older // than another one. @@ -194,13 +151,4 @@ export function intFromVersion(version) { /******************************************************************************/ -export { - broadcastMessage, - parsedURLromOrigin, - toBroaderHostname, - isDescendantHostname, - isDescendantHostnameOfIter, - intersectHostnameIters, - subtractHostnameIters, - strArrayEq, -}; +export const isScriptlet = a => a.startsWith('+js'); diff --git a/platform/mv3/extension/lib/codemirror/codemirror-ubol b/platform/mv3/extension/lib/codemirror/codemirror-ubol index 0cd9b7a77cd16..6a8aa61b29e49 160000 --- a/platform/mv3/extension/lib/codemirror/codemirror-ubol +++ b/platform/mv3/extension/lib/codemirror/codemirror-ubol @@ -1 +1 @@ -Subproject commit 0cd9b7a77cd166186ebdb483d6aac82f616685df +Subproject commit 6a8aa61b29e494ecede6e067ac3782c184a8008b diff --git a/platform/mv3/extension/lib/s14e-serializer b/platform/mv3/extension/lib/s14e-serializer new file mode 160000 index 0000000000000..1f028eb315c14 --- /dev/null +++ b/platform/mv3/extension/lib/s14e-serializer @@ -0,0 +1 @@ +Subproject commit 1f028eb315c14bb11f23f0ef6c4bf6c339d3b0b1 diff --git a/platform/mv3/extension/managed_storage.json b/platform/mv3/extension/managed_storage.json index 85446f2e63cfe..1771be6a8b697 100644 --- a/platform/mv3/extension/managed_storage.json +++ b/platform/mv3/extension/managed_storage.json @@ -28,6 +28,10 @@ "type": "array", "items": { "type": "string" } }, + "popupBlockMode": { + "title": "Enable/disable pop-up blocking", + "type": "boolean" + }, "showBlockedCount": { "title": "Enable/disable toolbar icon count badge", "type": "boolean" diff --git a/platform/mv3/firefox/ext-offscreen.js b/platform/mv3/firefox/ext-offscreen.js new file mode 100644 index 0000000000000..592a0d31f3941 --- /dev/null +++ b/platform/mv3/firefox/ext-offscreen.js @@ -0,0 +1,45 @@ +/******************************************************************************* + + uBlock Origin Lite - a comprehensive, MV3-compliant content blocker + Copyright (C) 2026-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock +*/ + +// Firefox does not support natively the offscreen API + +let offscreenContext = null; + +export const supportsOffscreenDocument = true; + +export async function createOffscreenDocument(path) { + const { promise, resolve, reject } = Promise.withResolvers(); + if ( offscreenContext !== null ) { + reject('Only one offscreen context allowed'); + return promise; + } + offscreenContext = document.createElement('iframe'); + offscreenContext.src = browser.runtime.getURL(path); + offscreenContext.onload = ( ) => { resolve(); }; + document.body.append(offscreenContext); + return promise; +} + +export async function closeOffscreenDocument() { + if ( offscreenContext === null ) { return; } + offscreenContext.remove(); + offscreenContext = null; +} diff --git a/platform/mv3/firefox/manifest.json b/platform/mv3/firefox/manifest.json index e2ca46cdbb2e2..a01a57f1ddf3f 100644 --- a/platform/mv3/firefox/manifest.json +++ b/platform/mv3/firefox/manifest.json @@ -54,11 +54,16 @@ "host_permissions": [ "" ], + "optional_permissions": [ + "userScripts" + ], "permissions": [ "activeTab", + "alarms", "declarativeNetRequest", "scripting", - "storage" + "storage", + "unlimitedStorage" ], "short_name": "uBO Lite", "version": "1.0", diff --git a/platform/mv3/make-rulesets.js b/platform/mv3/make-rulesets.js index 57e64a2ae07fd..ea8cab87204bf 100644 --- a/platform/mv3/make-rulesets.js +++ b/platform/mv3/make-rulesets.js @@ -19,8 +19,9 @@ Home: https://github.com/gorhill/uBlock */ -import * as makeScriptlet from './js/make-scriptlets.js'; -import * as sfp from './js/static-filtering-parser.js'; +import './lib/regexanalyzer/regex.js'; + +import * as makeScriptlets from './js/offscreen/make-scriptlets.js'; import { createHash, @@ -30,14 +31,21 @@ import { dnrRulesetFromRawLists, mergeRules, } from './js/static-dnr-filtering.js'; +import { + expandRemoveparamsRule, + minimizeRuleset, +} from './js/ubo-parser.js'; import { execSync } from 'node:child_process'; +import { fetchList } from './js/offscreen/fetch-list.js'; import fs from 'fs/promises'; -import { literalStrFromRegex } from './js/regex-analyzer.js'; +import { hostnameCompare } from './js/offscreen/make-utils.js'; +import { literalStrFromRegex } from './js/offscreen/regex-analyzer.js'; +import { makeCosmeticScripts } from './js/offscreen/make-cosmetic-filters.js'; import path from 'path'; import process from 'process'; import redirectResourcesMap from './js/redirect-resources.js'; -import { safeReplace } from './js/safe-replace.js'; +import { safeReplace } from './js/offscreen/safe-replace.js'; /******************************************************************************/ @@ -74,7 +82,6 @@ const env = [ 'mv3', 'ublock', 'ubol', - 'user_stylesheet', ...envExtra, ]; @@ -113,8 +120,6 @@ const logProgress = text => { process?.stdout?.write?.(text.length > 120 ? `${text.slice(0, 119)}… ` : `${text} `); }; -const isHnRegexOrPath = hn => hn.includes('/'); - /******************************************************************************/ async function fetchText(url, cacheDir) { @@ -191,8 +196,16 @@ const genericDetails = new Map(); const requiredRedirectResources = new Set(); let networkBad = new Set(); -// This will be used to sign our inserted `!#trusted on` directives -const secret = createHash('sha256').update(randomBytes(16)).digest('hex').slice(0,16); +/******************************************************************************/ + +// "secret" will be used to sign our inserted `!#trusted on` directives +const secret = await fs.readFile(`${cacheDir}/secret.txt`, { + encoding: 'utf8' +}).catch(( ) => { + const secret = createHash('sha256').update(randomBytes(16)).digest('hex').slice(0,16); + writeFile(`${cacheDir}/secret.txt`, secret); + return secret; +}); log(`Secret: ${secret}`, false); /******************************************************************************/ @@ -241,58 +254,31 @@ rePatternFromUrlFilter.restrHostnameAnchor2 = '^[^:]+://([^:/]+)?'; /******************************************************************************/ -async function fetchList(assetDetails) { - // Mind commit if present - const effectiveURL = url => { - return assetDetails.commit - ? url.replace('{commit}', assetDetails.commit) - : url; - }; - // Remember fetched URLs - const fetchedURLs = new Set(); - - // Fetch list and expand `!#include` directives - let parts = assetDetails.urls.map(url => ({ url: effectiveURL(url) })); - while ( parts.every(v => typeof v === 'string') === false ) { - const newParts = []; - for ( const part of parts ) { - if ( typeof part === 'string' ) { - newParts.push(effectiveURL(part)); - continue; - } - if ( fetchedURLs.has(effectiveURL(part.url)) ) { - newParts.push(''); - continue; - } - fetchedURLs.add(effectiveURL(part.url)); - if ( - assetDetails.trusted || - part.url.startsWith('https://ublockorigin.github.io/uAssets/filters/') - ) { - newParts.push(`!#trusted on ${secret}`); - } - newParts.push( - fetchText(effectiveURL(part.url), cacheDir).then(details => { - const { url, error } = details; - if ( error !== undefined ) { return details; } - const content = details.content.trim(); - if ( /* content === '' || */ /^<.*>$/.test(content) ) { - return { url, error: `Bad content: ${url}` }; - } - return { url, content }; - }) - ); - newParts.push(`!#trusted off ${secret}`); - } - if ( parts.some(v => typeof v === 'object' && v.error) ) { return; } - parts = await Promise.all(newParts); - parts = sfp.utils.preparser.expandIncludes(parts, env); +async function fetchListFromCache(assetDetails) { + const fname = assetDetails.id; + logProgress(`Reading locally cached ${platform}/${fname}`); + + const content = await fs.readFile(`${cacheDir}/${platform}/${fname}`, + { encoding: 'utf8' } + ).catch(( ) => { }); + if ( content !== undefined ) { + log(`\tFetched local ${fname}`); + return content; } - const text = parts.join('\n'); - if ( text === '' ) { - log('No filterset found', false); + const context = { + env, + secret, + trustedPrefixes: [ 'https://ublockorigin.github.io/uAssets/filters/' ], + }; + + const text = await fetchList(context, assetDetails); + writeFile(`${cacheDir}/${platform}/${fname}`, text); + + if ( Boolean(text) === false ) { + throw 'Filter list should not be empty'; } + return text; } @@ -587,7 +573,6 @@ async function processDnrRules(assetDetails, network, dnrRules) { const staticRules = await patchRuleset( dnrRules.filter(rule => isGood(rule) && isRegex(rule) === false) ); - log(`\tStatic rules: ${staticRules.length}`); log(staticRules .filter(rule => Array.isArray(rule._warning)) .map(rule => rule._warning.map(v => `\t\t${v}`)) @@ -597,7 +582,8 @@ async function processDnrRules(assetDetails, network, dnrRules) { const regexRules = await patchRuleset( dnrRules.filter(rule => isGood(rule) && isRegex(rule)) ); - log(`\tMaybe good (regexes): ${regexRules.length}`); + const minimizedRegexRuleset = minimizeRuleset(regexRules); + log(`\tMaybe good regexes (raw/minimized): ${regexRules.length}/${minimizedRegexRuleset.length}`); staticRules.forEach(rule => { if ( rule.action.redirect?.extensionPath === undefined ) { return; } @@ -606,6 +592,17 @@ async function processDnrRules(assetDetails, network, dnrRules) { ); }); + // Patch removeParams rules as needed + for ( const rule of staticRules ) { + if ( rule.action.redirect?.transform?.queryTransform?.removeParams ) { + expandRemoveparamsRule(rule, staticRules); + } + } + + // Minimize rulesets + const minimizedStaticRuleset = minimizeRuleset(staticRules); + log(`\tStatic rules (raw/minimized): ${staticRules.length}/${minimizedStaticRuleset.length}`); + const urlskips = new Map(); for ( const rule of dnrRules ) { if ( isURLSkip(rule) === false ) { continue; } @@ -654,12 +651,12 @@ async function processDnrRules(assetDetails, network, dnrRules) { log(bad.map(rule => rule._error.map(v => `\t\t${v}`)).join('\n'), true); writeFile(`${rulesetDir}/main/${assetDetails.id}.json`, - toJSONRuleset(staticRules) + toJSONRuleset(minimizedStaticRuleset) ); - if ( regexRules.length !== 0 ) { + if ( minimizedRegexRuleset.length !== 0 ) { writeFile(`${rulesetDir}/regex/${assetDetails.id}.json`, - toJSONRuleset(regexRules) + toJSONRuleset(minimizedRegexRuleset) ); } @@ -670,10 +667,10 @@ async function processDnrRules(assetDetails, network, dnrRules) { } return { - total: staticRules.length + regexRules.length, - plain: staticRules.length, + total: minimizedStaticRuleset.length + minimizedRegexRuleset.length, + plain: minimizedStaticRuleset.length, + regex: minimizedRegexRuleset.length, rejected: bad.length, - regex: regexRules.length, urlskip: urlskips.size || undefined, }; } @@ -726,7 +723,7 @@ async function processGenericCosmeticFilters( assetDetails, selectorList, exceptionList, - declarativeMap + specificMap ) { const exceptionSet = new Set( exceptionList && @@ -754,11 +751,12 @@ async function processGenericCosmeticFilters( // Specific exceptions const exceptionMap = new Map(); - if ( declarativeMap ) { - for ( const [ exception, details ] of declarativeMap ) { + if ( specificMap ) { + for ( const [ exception, details ] of specificMap ) { if ( details.rejected ) { continue; } if ( details.matches !== undefined ) { continue; } if ( details.excludeMatches === undefined ) { continue; } + if ( exception.startsWith('{') ) { continue; } for ( const hn of details.excludeMatches ) { const exceptions = exceptionMap.get(hn); if ( exceptions === undefined ) { @@ -840,103 +838,18 @@ const scriptletJsonReplacer = (k, v) => { /******************************************************************************/ -const hostnameCompare = (a, b) => { - const d = a.length - b.length; - if ( d !== 0 ) { return d; } - return a < b ? -1 : 1; -}; - -/******************************************************************************/ - -async function processCosmeticFilters(assetDetails, realm, mapin) { - if ( mapin === undefined ) { return 0; } - if ( mapin.size === 0 ) { return 0; } - - // Collate all distinct selectors - const allSelectors = new Map(); - const allHostnames = new Map(); - const allRegexesOrPaths = new Map(); - let hasEntities = false; - - const storeHostnameSelectorPair = (hn, iSelector) => { - if ( isHnRegexOrPath(hn) ) { - if ( allRegexesOrPaths.has(hn) === false ) { - allRegexesOrPaths.set(hn, new Set()); - } - allRegexesOrPaths.get(hn).add(iSelector); - } else { - if ( allHostnames.has(hn) === false ) { - allHostnames.set(hn, new Set()); - } - allHostnames.get(hn).add(iSelector); - hasEntities ||= hn.endsWith('.*'); - } - }; - - for ( const [ selector, details ] of mapin ) { - if ( details.rejected ) { continue; } - if ( allSelectors.has(selector) === false ) { - allSelectors.set(selector, allSelectors.size); - } - const iSelector = allSelectors.get(selector); - if ( details.matches ) { - for ( const hn of details.matches ) { - storeHostnameSelectorPair(hn, iSelector); - } - } - if ( details.excludeMatches ) { - for ( const hn of details.excludeMatches ) { - storeHostnameSelectorPair(hn, ~iSelector); - } - } - } - const allSelectorLists = new Map(); - - const ilistFromSelectorSet = selectorSet => { - const list = JSON.stringify(Array.from(selectorSet).sort()).slice(1, -1); - if ( allSelectorLists.has(list) === false ) { - allSelectorLists.set(list, allSelectorLists.size); - } - return allSelectorLists.get(list); - }; - - for ( const [ hn, selectorSet ] of allHostnames ) { - allHostnames.set(hn, ilistFromSelectorSet(selectorSet)); - } - for ( const [ regexOrPath, selectorSet ] of allRegexesOrPaths ) { - allRegexesOrPaths.set(regexOrPath, ilistFromSelectorSet(selectorSet)); - } - - const sortedHostnames = Array.from(allHostnames.keys()).toSorted(hostnameCompare); - - const data = { - selectors: Array.from(allSelectors.keys()), - selectorLists: Array.from(allSelectorLists.keys()), - selectorListRefs: sortedHostnames.map(a => allHostnames.get(a)), - hostnames: sortedHostnames, - hasEntities, - regexes: Array.from(allRegexesOrPaths) - .filter(a => a[0].startsWith('/') && a[0].endsWith('/')) - .map(a => { - const restr = a[0].slice(1,-1); - return [ literalStrFromRegex(restr).slice(0,8), restr, a[1] ] - }).flat(), - }; - writeFile(`${scriptletDir}/${realm}/${assetDetails.id}.json`, JSON.stringify(data)); - - // The cosmetic filters will be injected programmatically as content - // script and the decisions to activate the cosmetic filters will be - // done at injection time according to the document's hostname. - const originalScriptletMap = await loadAllSourceScriptlets(); - let patchedScriptlet = originalScriptletMap.get(`css-${realm}`).replace( - 'self.$rulesetId$', - JSON.stringify(assetDetails.id) +async function processCosmeticFilters(assetDetails, mapin) { + const template = await fs.readFile(`./scriptlets/css-specific.template.js`, { + encoding: 'utf8', + }); + const result = await makeCosmeticScripts(assetDetails.id, mapin); + if ( result === undefined ) { return 0; } + writeFile(`${scriptletDir}/specific/${assetDetails.id}.json`, JSON.stringify(result.data)); + writeFile(`${scriptletDir}/specific/${assetDetails.id}.js`, + template.replace('self.$rulesetId$', JSON.stringify(assetDetails.id)) ); - writeFile(`${scriptletDir}/${realm}/${assetDetails.id}.js`, patchedScriptlet); - - log(`CSS-${realm}: ${allSelectors.size} distinct filters for ${allHostnames.size} distinct hostnames`); - - return sortedHostnames.length + allRegexesOrPaths.size; + log(`CSS-specific: ${result.selectorCount} distinct filters for ${result.hostnameCount} distinct hostnames`); + return result.hostnameCount + result.regexCount; } /******************************************************************************/ @@ -947,13 +860,12 @@ async function processScriptletFilters(assetDetails, mapin) { const { id } = assetDetails; for ( const details of mapin.values() ) { - makeScriptlet.compile(id, details); + makeScriptlets.compile(id, details); } - const template = await fs.readFile( - './scriptlets/scriptlet.template.js', - { encoding: 'utf8' } - ); - const result = makeScriptlet.commit(id, template); + const template = await fs.readFile('./js/offscreen/scriptlet.template.js', { + encoding: 'utf8', + }); + const result = makeScriptlets.commit(id, template); const stats = {}; let count = 0; if ( result.MAIN ) { @@ -969,7 +881,7 @@ async function processScriptletFilters(assetDetails, mapin) { if ( count !== 0 ) { scriptletStats.set(id, stats); } - makeScriptlet.reset(); + makeScriptlets.reset(); return count; } @@ -981,6 +893,7 @@ async function processPopupRules(assetDetails, popupRules) { const { condition } = rule; if ( condition.domainType ) { return data; } if ( condition.initiatorDomains ) { return data; } + if ( condition.excludedInitiatorDomains ) { return data; } const { type } = rule.action; if ( type !== 'block' && type !== 'allow' ) { return data; } const realm = type === 'block' ? data.block : data.allow; @@ -998,16 +911,32 @@ async function processPopupRules(assetDetails, popupRules) { } if ( re === undefined ) { return data; } const token = literalStrFromRegex(re).slice(0, 7); - const key = `${isUrlFilterCaseSensitive ? ' ' : 'i'}${token}`; - if ( realm.regexes.has(key) ) { - realm.regexes.set(key, `${realm.regexes.get(key)}|${re}`); - } else { - realm.regexes.set(key, re); + const details = realm.regexes.get(token) ?? { token, rules: [] }; + if ( details.rules.length === 0 ) { + realm.regexes.set(token, details) + } + const entry = { re, f: isUrlFilterCaseSensitive ? '' : 'i' }; + details.rules.push(entry); + if ( condition.requestDomains ) { + entry.to = condition.requestDomains.sort(hostnameCompare); + } + if ( condition.excludedRequestDomains ) { + entry.xto = condition.excludedRequestDomains.sort(hostnameCompare); } return data; } if ( Array.isArray(condition.requestDomains) ) { - realm.hostnames = realm.hostnames.concat(condition.requestDomains); + realm.hostnames = realm.hostnames.concat( + condition.requestDomains + ); + } + // https://github.com/uBlockOrigin/uAssets/issues/33581 + if ( type === 'block' ) { + if ( Array.isArray(condition.excludedRequestDomains) ) { + data.allow.hostnames = data.allow.hostnames.concat( + condition.excludedRequestDomains + ); + } } return data; }; @@ -1026,9 +955,13 @@ async function processPopupRules(assetDetails, popupRules) { const count = data.block.hostnames.length + data.block.regexes.size; if ( count === 0 ) { return; } data.block.hostnames = data.block.hostnames.toSorted(hostnameCompare); - data.block.regexes = Array.from(data.block.regexes).flat(); + data.block.regexes = Array.from(data.block.regexes.values()).map(a => + [ a.token, JSON.stringify(a.rules) ] + ).flat(); data.allow.hostnames = data.allow.hostnames.toSorted(hostnameCompare); - data.allow.regexes = Array.from(data.allow.regexes).flat(); + data.allow.regexes = Array.from(data.allow.regexes.values()).map(a => + [ a.token, JSON.stringify(a.rules) ] + ).flat(); const originalScriptletMap = await loadAllSourceScriptlets(); let patchedScriptlet = originalScriptletMap.get(`prevent-popup`); patchedScriptlet = safeReplace(patchedScriptlet, @@ -1052,7 +985,7 @@ async function rulesetFromURLs(assetDetails) { log(`Listset for '${assetDetails.id}':`); if ( assetDetails.text === undefined && assetDetails.urls.length !== 0 ) { - const text = await fetchList(assetDetails); + const text = await fetchListFromCache(assetDetails); if ( text === undefined ) { process.exit(1); } @@ -1073,8 +1006,12 @@ async function rulesetFromURLs(assetDetails) { if ( assetDetails.text === '' ) { return; } + const excludedResources = new Set([ + 'click2load.html', + ]); const extensionPaths = []; for ( const [ fname, details ] of redirectResourcesMap ) { + if ( excludedResources.has(fname) ) { continue; } const path = `/web_accessible_resources/${fname}`; extensionPaths.push([ fname, path ]); if ( details.alias === undefined ) { continue; } @@ -1126,9 +1063,8 @@ async function rulesetFromURLs(assetDetails) { } // Split cosmetic filters into two groups: declarative and procedural - const declarativeCosmetic = new Map(); - const proceduralCosmetic = new Map(); const rejectedCosmetic = []; + const specificCosmetic = new Map(); if ( results.specificCosmetic ) { for ( const [ selector, details ] of results.specificCosmetic ) { if ( details.rejected ) { @@ -1136,12 +1072,12 @@ async function rulesetFromURLs(assetDetails) { continue; } if ( selector.startsWith('{') === false ) { - declarativeCosmetic.set(selector, details); - continue; + specificCosmetic.set(selector, details); + } else { + const parsed = JSON.parse(selector); + parsed.raw = undefined; + specificCosmetic.set(JSON.stringify(parsed), details); } - const parsed = JSON.parse(selector); - parsed.raw = undefined; - proceduralCosmetic.set(JSON.stringify(parsed), details); } } if ( rejectedCosmetic.length !== 0 ) { @@ -1174,19 +1110,13 @@ async function rulesetFromURLs(assetDetails) { assetDetails, results.genericCosmeticFilters, results.genericCosmeticExceptions, - declarativeCosmetic + specificCosmetic ); const specificCosmeticStats = await processCosmeticFilters( assetDetails, - 'specific', - declarativeCosmetic + specificCosmetic ); - const proceduralStats = await processCosmeticFilters( - assetDetails, - 'procedural', - proceduralCosmetic - ); await processScriptletFilters(assetDetails, results.scriptlet); rulesetDetails.push({ @@ -1218,7 +1148,6 @@ async function rulesetFromURLs(assetDetails) { css: { generic: genericCosmeticStats, specific: specificCosmeticStats, - procedural: proceduralStats, }, popups: popupStats, }); diff --git a/platform/mv3/rulesets.json b/platform/mv3/rulesets.json index 5c3e3f4e9430c..33ada91b7c584 100644 --- a/platform/mv3/rulesets.json +++ b/platform/mv3/rulesets.json @@ -90,16 +90,6 @@ ], "homeURL": "https://github.com/uBlockOrigin/uAssets" }, - { - "id": "dpollock-0", - "name": "Dan Pollock’s hosts file", - "enabled": false, - "excludedPlatforms": [ "safari" ], - "urls": [ - "https://someonewhocares.org/hosts/hosts" - ], - "homeURL": "https://someonewhocares.org/hosts/" - }, { "id": "adguard-spyware-url", "name": "AdGuard/uBO – URL Tracking Protection", @@ -302,7 +292,7 @@ "id": "fra-0", "group": "regions", "lang": "ar br ff fr lb oc son", - "name": "🇫🇷fr 🇨🇦ca: AdGuard Français", + "name": "🇫🇷fr 🇧🇪be 🇨🇦ca: AdGuard Français", "tags": "ads french", "enabled": false, "urls": [ @@ -434,13 +424,13 @@ "id": "kor-1", "group": "regions", "lang": "ko", - "name": "🇰🇷kr: List-KR Classic", + "name": "🇰🇷kr: 한국어 (Korean)", "tags": "ads korean 한국어", "enabled": false, "urls": [ - "https://cdn.jsdelivr.net/npm/@list-kr/filterslists@latest/dist/filterslist-uBlockOrigin-classic.txt" + "https://cdn.jsdelivr.net/npm/@filteringdev/filterslists-ko@latest/dist/filterslist-uBlockOrigin-classic.txt" ], - "homeURL": "https://github.com/List-KR/List-KR#readme" + "homeURL": "https://github.com/FilteringDev/filterslists-KO#filteringdevfilterslists-ko" }, { "id": "ltu-0", @@ -505,7 +495,8 @@ { "id": "pol-0", "group": "regions", - "lang": "szl pl _", + "parent": "🇵🇱pl: Polskie listy filtrów", + "lang": "szl pl", "name": "🇵🇱pl: Oficjalne Polskie Filtry do uBlocka Origin", "tags": "ads polish polski", "enabled": false, @@ -514,6 +505,20 @@ ], "homeURL": "https://github.com/MajkiIT/polish-ads-filter" }, + { + "id": "pol-3", + "group": "regions", + "parent": "🇵🇱pl: Polskie listy filtrów", + "lang": "szl pl", + "name": "🇵🇱pl: CERT.PL's Warning List", + "tags": "malware polish polski", + "enabled": false, + "excludedPlatforms": [ "safari" ], + "urls": [ + "https://hole.cert.pl/domains/v2/domains_ublock.txt" + ], + "homeURL": "https://cert.pl/lista-ostrzezen/" + }, { "id": "rou-1", "group": "regions", diff --git a/platform/mv3/safari/css-api.js b/platform/mv3/safari/css-api.js index e9b8817f4a039..88c7b2796c8a9 100644 --- a/platform/mv3/safari/css-api.js +++ b/platform/mv3/safari/css-api.js @@ -35,7 +35,7 @@ }, }; - self.addEventListener('pageshow', ( ) => { + self.addEventListener('pagereveal', ( ) => { chrome.runtime.sendMessage({ what: 'insertCSS', css: Array.from(inserted).join('\n'), diff --git a/platform/mv3/safari/css-user.js b/platform/mv3/safari/css-user.js index 0f5caedaf2cbe..ceb96e528e930 100644 --- a/platform/mv3/safari/css-user.js +++ b/platform/mv3/safari/css-user.js @@ -23,34 +23,59 @@ /******************************************************************************/ -const docURL = new URL(document.baseURI); -const details = await chrome.runtime.sendMessage({ - what: 'injectCustomFilters', - hostname: docURL.hostname, -}).catch(( ) => { -}); - -if ( details?.proceduralSelectors?.length ) { - if ( self.ProceduralFiltererAPI ) { +async function uBOL_cssUserActivate() { + if ( self.customFilters ) { return; } + + const docURL = new URL(document.baseURI); + + const details = await chrome.runtime.sendMessage({ + what: 'injectCustomFilters', + hostname: docURL.hostname, + }).catch(( ) => { + }); + self.customFilters = details; + if ( Boolean(details) === false ) { return; } + + if ( details?.proceduralSelectors?.length ) { + if ( self.ProceduralFiltererAPI === undefined ) { + self.ProceduralFiltererAPI = chrome.runtime.sendMessage({ + what: 'injectCSSProceduralAPI' + }).catch(( ) => { + }); + } + await self.ProceduralFiltererAPI; self.customProceduralFiltererAPI = new self.ProceduralFiltererAPI(); - self.customProceduralFiltererAPI.addSelectors( - details.proceduralSelectors.map(a => JSON.parse(a)) - ); + const selectors = details.proceduralSelectors.map(a => JSON.parse(a)); + const declaratives = selectors.filter(a => a.cssable); + if ( declaratives.length !== 0 ) { + self.customProceduralFiltererAPI.addDeclaratives(declaratives); + } + const procedurals = selectors.filter(a => !a.cssable); + if ( procedurals.length !== 0 ) { + self.customProceduralFiltererAPI.addProcedurals(procedurals); + } + } + + if ( details?.plainSelectors?.length ) { + const selectors = details.plainSelectors; + self.cssAPI.insert(`${selectors.join(',\n')}{display:none!important;}`); } } -if ( details?.plainSelectors?.length ) { - const selectors = details.plainSelectors; - self.addEventListener('pageshow', ( ) => { - chrome.runtime.sendMessage({ - what: 'insertCSS', - css: `${selectors.join(',\n')}{display:none!important;}`, - }).catch(( ) => { - }); - }); +async function uBOL_cssUserStart() { + if ( self.cssUserPendingOp === undefined ) { + self.cssUserPendingOp = Promise.resolve(); + } + self.cssUserPendingOp = self.cssUserPendingOp.then(uBOL_cssUserActivate); + await self.cssUserPendingOp; + if ( Boolean(self.customFilters) === false ) { return; } + self.removeEventListener('pagereveal', uBOL_cssUserStart); } -self.customFilters = details; +await uBOL_cssUserStart(); + +if ( self.customFilters ) { return; } +self.addEventListener('pagereveal', uBOL_cssUserStart); /******************************************************************************/ diff --git a/platform/mv3/safari/ext-compat.js b/platform/mv3/safari/ext-compat.js index 21ba4226105f3..73d0354e5ee25 100644 --- a/platform/mv3/safari/ext-compat.js +++ b/platform/mv3/safari/ext-compat.js @@ -19,7 +19,7 @@ Home: https://github.com/gorhill/uBlock */ -import { deepEquals } from './utils.js'; +import { deepEquals } from './deep-compare.js'; export const webext = self.browser; diff --git a/platform/mv3/edge/patch-ruleset.js b/platform/mv3/safari/ext-offscreen.js similarity index 58% rename from platform/mv3/edge/patch-ruleset.js rename to platform/mv3/safari/ext-offscreen.js index 656849f9b39dd..9e73928a11b8d 100644 --- a/platform/mv3/edge/patch-ruleset.js +++ b/platform/mv3/safari/ext-offscreen.js @@ -1,7 +1,7 @@ /******************************************************************************* - uBlock Origin - a comprehensive, efficient content blocker - Copyright (C) 2025-present Raymond Hill + uBlock Origin Lite - a comprehensive, MV3-compliant content blocker + Copyright (C) 2026-present Raymond Hill This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,20 +19,13 @@ Home: https://github.com/gorhill/uBlock */ -function patchRule(rule, out) { - const { condition } = rule; - if ( Array.isArray(condition.responseHeaders) ) { - if ( condition.regexFilter === undefined ) { return; } - } - out.push(rule); - return rule; +// Safari does not support the offscreen API natively and there is no +// workaround. + +export const supportsOffscreenDocument = false; + +export async function createOffscreenDocument() { } -export function patchRuleset(ruleset) { - const out = []; - for ( const rule of ruleset ) { - if ( patchRule(rule, out) ) { continue; } - console.log(`\tReject ${JSON.stringify(rule)}`); - } - return out; +export async function closeOffscreenDocument() { } diff --git a/platform/mv3/safari/manifest.json b/platform/mv3/safari/manifest.json index ce029cdc1be44..96b0406705296 100644 --- a/platform/mv3/safari/manifest.json +++ b/platform/mv3/safari/manifest.json @@ -45,6 +45,7 @@ ], "permissions": [ "activeTab", + "alarms", "declarativeNetRequest", "declarativeNetRequestWithHostAccess", "scripting", diff --git a/publish-extension b/publish-extension index b245171eac43e..5798bcb1ce905 160000 --- a/publish-extension +++ b/publish-extension @@ -1 +1 @@ -Subproject commit b245171eac43ed1faeecff4b5d277044cdbcdbea +Subproject commit 5798bcb1ce905222e1ca559c538eebb98108cd84 diff --git a/src/_locales/ar/messages.json b/src/_locales/ar/messages.json index df3c75f262ebd..d57e046372f88 100644 --- a/src/_locales/ar/messages.json +++ b/src/_locales/ar/messages.json @@ -12,11 +12,11 @@ "description": "English: uBlock₀ — Dashboard" }, "dashboardUnsavedWarning": { - "message": "تنبيه! لديك تغييرات لم تقم بحفظها", + "message": "تنبيه: لديك تغييرات لم تقم بحفظها!", "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "إبقى", + "message": "البقاء هنا", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { @@ -28,15 +28,15 @@ "description": "appears as tab name in dashboard" }, "3pPageName": { - "message": "قوائم الفلاتر", + "message": "قوائم خيارات التصفية", "description": "appears as tab name in dashboard" }, "1pPageName": { - "message": "الفلاتر الخاصة بي", + "message": "المصفيات الخاصة بي", "description": "appears as tab name in dashboard" }, "rulesPageName": { - "message": "القواعد الخاصة بي", + "message": "قواعدي", "description": "appears as tab name in dashboard" }, "whitelistPageName": { @@ -60,7 +60,7 @@ "description": "appears as tab name in dashboard" }, "assetViewerPageName": { - "message": "uBlock₀ — مُعاين العناصر", + "message": "uBlock₀ — عارض الأصول", "description": "Title for the asset viewer page" }, "advancedSettingsPageName": { @@ -68,19 +68,19 @@ "description": "Title for the advanced settings page" }, "popupPowerSwitchInfo": { - "message": "اضغط: لتعطيل/تشغيل ميكروبلوك لهذا الموقع.\n\nCtrl+click لتعطيل ميكروبلوك لهذه الصفحة فقط.", + "message": "انقر: تعطيل/تمكين uBlock₀ لهذا الموقع.\n\nCtrl+انقر: تعطيل uBlock₀ على هذه الصفحة فقط.", "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." }, "popupPowerSwitchInfo1": { - "message": "اضغط لتعطيل uBlock₀ لهذا الموقع.\n\nCtrl+click لتعطيل uBlock₀ لهذه الصفحة فقط.", + "message": "انقر لتعطيل uBlock₀ لهذا الموقع.\n\nCtrl+انقر لتعطيل uBlock₀ لهذه الصفحة فقط.", "description": "Message to be read by screen readers" }, "popupPowerSwitchInfo2": { - "message": "اضغط لتفعيل uBlock₀ لهذا الموقع.", + "message": "انقر لتفعيل uBlock₀ لهذا الموقع.", "description": "Message to be read by screen readers" }, "popupBlockedRequestPrompt": { - "message": "تم منع الطلبات", + "message": "الطلبات المحجوبة", "description": "English: requests blocked" }, "popupBlockedOnThisPagePrompt": { @@ -88,7 +88,7 @@ "description": "English: on this page" }, "popupBlockedStats": { - "message": "{{count}} أو {{percent}}%", + "message": "{{count}} ({{percent}}%)", "description": "Example: 15 (13%)" }, "popupBlockedSinceInstallPrompt": { @@ -100,11 +100,11 @@ "description": "English: or" }, "popupBlockedOnThisPage_v2": { - "message": "محجوب على هذه الصفحة", + "message": "محجوب في هذه الصفحة", "description": "For the new mobile-friendly popup design" }, "popupBlockedSinceInstall_v2": { - "message": "حُجِب منذ التنصيب", + "message": "محجوب منذ التثبيت", "description": "For the new mobile-friendly popup design" }, "popupDomainsConnected_v2": { @@ -112,7 +112,7 @@ "description": "For the new mobile-friendly popup design" }, "popupTipDashboard": { - "message": "إضغط لفتح لوحة التحكم", + "message": "انقر لفتح لوحة التحكم", "description": "English: Click to open the dashboard" }, "popupTipZapper": { @@ -124,7 +124,7 @@ "description": "English: Enter element picker mode" }, "popupTipLog": { - "message": "إفتح سجل طلبات الشبكة", + "message": "افتح السجل", "description": "Tooltip used for the logger icon in the panel" }, "popupTipReport": { @@ -132,7 +132,7 @@ "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipNoPopups": { - "message": "تفعيل أو تعطيل النوافذ منبثقة لهذا الموقع", + "message": "تبديل حجب جميع النوافذ المنبثقة لهذا الموقع", "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoPopups1": { @@ -140,35 +140,35 @@ "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoPopups2": { - "message": "أضغط للوقف منع جميع النوافذ المنبثقة لهذا الموقع", + "message": "انقر لإلغاء حجب جميع النوافذ المنبثقة في هذا الموقع", "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoLargeMedia": { - "message": "تفعيل أو تعطيل حجب عناصر الوسائط الكبيرة لهذا الموقع", + "message": "تبديل حجب عناصر الوسائط الكبيرة لهذا الموقع", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoLargeMedia1": { - "message": "اضغط لحجب عناصر الوسائط الكبيرة لهذا الموقع", + "message": " انقر لحجب عناصر الوسائط الكبيرة في هذا الموقع", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoLargeMedia2": { - "message": "أضغط للوقف منع عناصر الوسائط الكبيرة لهذا الموقع", + "message": "انقر لإلغاء حجب عناصر الوسائط الكبيرة في هذا الموقع", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoCosmeticFiltering": { - "message": "تفعيل أو تعطيل الفلترة التجميلية لهذا الموقع", + "message": "تبديل تصفية المظهر لهذا الموقع", "description": "Tooltip for the no-cosmetic-filtering per-site switch" }, "popupTipNoCosmeticFiltering1": { - "message": "اضغط لتعطيل الفلترة التجميلية لهذا الموقع", + "message": "انقر لتعطيل تصفية المظهر في هذا الموقع", "description": "Tooltip for the no-cosmetic-filtering per-site switch" }, "popupTipNoCosmeticFiltering2": { - "message": "اضغط لتشغيل الفلترة التجميلية لهذا الموقع", + "message": "انقر لتفعيل تصفية المظهر في هذا الموقع", "description": "Tooltip for the no-cosmetic-filtering per-site switch" }, "popupTipNoRemoteFonts": { - "message": "تفعيل أو تعطيل حجب الخطوط الخارجية لهذا الموقع", + "message": "تبديل حجب الخطوط الخارجية لهذا الموقع", "description": "Tooltip for the no-remote-fonts per-site switch" }, "popupTipNoRemoteFonts1": { @@ -176,7 +176,7 @@ "description": "Tooltip for the no-remote-fonts per-site switch" }, "popupTipNoRemoteFonts2": { - "message": "أضغط للسماح للخطوط الخارجية لهذا الموقع", + "message": " انقر لإلغاء حجب الخطوط الخارجية لهذا الموقع", "description": "Tooltip for the no-remote-fonts per-site switch" }, "popupTipNoScripting1": { @@ -188,7 +188,7 @@ "description": "Tooltip for the no-scripting per-site switch" }, "popupNoPopups_v2": { - "message": "نوافذ منبثقة", + "message": "النوافذ المنبثقة", "description": "Caption for the no-popups per-site switch" }, "popupNoLargeMedia_v2": { @@ -196,7 +196,7 @@ "description": "Caption for the no-large-media per-site switch" }, "popupNoCosmeticFiltering_v2": { - "message": "المرشحات التجميلية", + "message": "تصفية المظهر", "description": "Caption for the no-cosmetic-filtering per-site switch" }, "popupNoRemoteFonts_v2": { @@ -220,15 +220,15 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "الشروط المؤقتة: هذا العمود يتعلق بالقواعد التي تنطبق فقط على الموقع المزار حاليا.\nالشروط المؤقتة تحل محل الشروط العامة.", + "message": "القواعد المحلية: هذا العمود مخصص للقواعد التي تنطبق على الموقع الحالي فقط.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { - "message": "إضغط لحفظ التغييرات بشكل دائم.", + "message": "انقر لحفظ التغييرات بشكل دائم.", "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." }, "popupTipRevertRules": { - "message": "إضغط لإعادة التغييرات للوضع السابق.", + "message": "انقر لإعادة التغييرات للوضع السابق.", "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." }, "popupAnyRulePrompt": { @@ -252,11 +252,11 @@ "description": "" }, "popup1pScriptRulePrompt": { - "message": "سكربتات من الطرف الاول", + "message": "سكريبتات من الطرف الاول", "description": "" }, "popup3pScriptRulePrompt": { - "message": "سكربتات من طرف خارجي", + "message": "سكريبتات من طرف خارجي", "description": "" }, "popup3pFrameRulePrompt": { @@ -276,7 +276,7 @@ "description": "Example of use: Version 1.26.4" }, "popup3pScriptFilter": { - "message": "برنامَج نصي", + "message": "سكريبت", "description": "Appears as an option to filter out firewall rows" }, "popup3pFrameFilter": { @@ -300,27 +300,27 @@ "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" }, "pickerNetFilters": { - "message": "فلاتر الشبكة", + "message": "خيارات تصفية الشبكة", "description": "English: header for a type of filter in the element picker dialog" }, "pickerCosmeticFilters": { - "message": "فلاتر تجميلية", + "message": "خيارات تصفية المظهر", "description": "English: Cosmetic filters" }, "pickerCosmeticFiltersHint": { - "message": "إضغط، إضغط مع Ctrl", + "message": "انقر، أو انقر مع الضغط على Ctrl", "description": "English: Click, Ctrl-click" }, "pickerContextMenuEntry": { - "message": "حجب العنصر...", + "message": "حجب العنصر…", "description": "An entry in the browser's contextual menu" }, "settingsCollapseBlockedPrompt": { - "message": "اخفاء مكان العناصر المحجوبه", + "message": "إخفاء المواضع المحجوزة للعناصر المحجوبة", "description": "English: Hide placeholders of blocked elements" }, "settingsIconBadgePrompt": { - "message": "عرض عدد طلبات المحضوره على الايقونه", + "message": "عرض عدد الطلبات المحجوبة على الأيقونة", "description": "English: Show the number of blocked requests on the icon" }, "settingsTooltipsPrompt": { @@ -328,15 +328,15 @@ "description": "A checkbox in the Settings pane" }, "settingsContextMenuPrompt": { - "message": "إستخدم لائحة السياق في المكان المناسب", + "message": "استخدم قائمة السياق عند الاقتضاء", "description": "English: Make use of context menu where appropriate" }, "settingsColorBlindPrompt": { - "message": "وضع عمى الألوان", + "message": "مناسب للأشخاص المصابين بعمى الألوان", "description": "English: Color-blind friendly" }, "settingsAppearance": { - "message": "مظهر", + "message": "المظهر", "description": "Section for controlling user interface appearance" }, "settingsThemeLabel": { @@ -352,7 +352,7 @@ "description": "" }, "settingsAdvancedUserPrompt": { - "message": "أنا مستخدم ذو خبرة (قراءة إجبارية)", + "message": "أنا مستخدم متقدم", "description": "Checkbox to let user access advanced, technical features" }, "settingsPrefetchingDisabledPrompt": { @@ -364,23 +364,23 @@ "description": "English: " }, "settingsWebRTCIPAddressHiddenPrompt": { - "message": "منع WebRTC من كشف عنوان الـ IP المحلي", + "message": "منع WebRTC من تسريب عناوين IP المحلية", "description": "English: " }, "settingPerSiteSwitchGroup": { - "message": "السلوك الإفتراضي", + "message": "السلوك الافتراضي", "description": "" }, "settingPerSiteSwitchGroupSynopsis": { - "message": "هذه السلوكيات الإفتراضية يمكن إستبدالها في كل حالة", + "message": "يمكن تجاوز هذه السلوكيات الافتراضية على أساس كل موقع على حدة", "description": "" }, "settingsNoCosmeticFilteringPrompt": { - "message": "تعطيل الفلترة التجميلية", + "message": "تعطيل تصفية المظهر", "description": "" }, "settingsNoLargeMediaPrompt": { - "message": "احجب عناصر الوسائط الأكبر من {{input}} كيلو بايت", + "message": "حجب عناصر الوسائط الأكبر من {{input}} كيلوبايت", "description": "" }, "settingsNoRemoteFontsPrompt": { @@ -396,7 +396,7 @@ "description": "background information: https://github.com/gorhill/uBlock/issues/3150" }, "settingsUncloakCnamePrompt": { - "message": "فك الأسماء المتعارف عليها", + "message": "كشف الأسماء القانونية", "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" }, "settingsAdvanced": { @@ -404,7 +404,7 @@ "description": "Section for controlling advanced-user settings" }, "settingsAdvancedSynopsis": { - "message": "ميزات مناسبة فقط للمستخدمين التقنيين", + "message": "ميزات مخصصة للمستخدمين التقنيين فقط", "description": "Description of section controlling advanced-user settings" }, "settingsAdvancedUserSettings": { @@ -412,15 +412,15 @@ "description": "For the tooltip of a link which gives access to advanced settings" }, "settingsLastRestorePrompt": { - "message": "آخر إسترجاع:", + "message": "آخر عملية استعادة:", "description": "English: Last restore:" }, "settingsLastBackupPrompt": { - "message": "آخر نسخ إحتياطي:", + "message": "آخر نسخة احتياطية:", "description": "English: Last backup:" }, "3pListsOfBlockedHostsPrompt": { - "message": "{{netFilterCount}} من فلاتر الشبكه + {{cosmeticFilterCount}} فلاتر تجميليه:", + "message": "{{netFilterCount}} من خيارات تصفية الشبكة + {{cosmeticFilterCount}} من خيارات تصفية المظهر من:", "description": "Appears at the top of the _3rd-party filters_ pane" }, "3pListsOfBlockedHostsPerListStats": { @@ -428,35 +428,35 @@ "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "3pAutoUpdatePrompt1": { - "message": "تحديث تلقائي للستات الفلاتر", + "message": "تحديث تلقائي لبيانات قوائم التصفية", "description": "A checkbox in the _3rd-party filters_ pane" }, "3pUpdateNow": { - "message": "حدث الان", + "message": "تحديث الآن", "description": "A button in the in the _3rd-party filters_ pane" }, "3pPurgeAll": { - "message": "نظف جميع المخابئ", + "message": "مسح جميع الملفات المؤقتة", "description": "A button in the in the _3rd-party filters_ pane" }, "3pParseAllABPHideFiltersPrompt1": { - "message": "تحليل وتطبيق فلاتر التجميليه", + "message": "تحليل خيارات تصفية المظهر وتطبيقها", "description": "English: Parse and enforce Adblock+ element hiding filters." }, "3pParseAllABPHideFiltersInfo": { - "message": "التشريحات التجميلية تعمل لإزالة العناصر في صفحة الويب التي تعتبر إزعاج بصريًا و تلك التي لا يمكن حجبها عن طريق محركات التشريحات القائمة على طلبات الشبكة.", + "message": "تستخدم تصفية المظهر لإخفاء العناصر الموجودة في صفحة الويب التي تعد مصدر إزعاج بصري، و لا يمكن حجبها بواسطة محركات التصفية القائمة على طلبات الشبكة.", "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." }, "3pIgnoreGenericCosmeticFilters": { - "message": "تجاهل الفلاتر التجميلية العامة", + "message": "تجاهل خيارات تصفية المظهر العامة", "description": "This will cause uBO to ignore all generic cosmetic filters." }, "3pIgnoreGenericCosmeticFiltersInfo": { - "message": "التشريحات التجميلية العمومية هي الفلاتر التجميلية التي تنطبق على كل مواقع الإنترنت. تفعيل هذا الخيار سوف يترك مساحة أقل من الذاكرة و قوة المعالجة للاستعمال من قبل صفحات الويب كنتيجة لمعالجة التشريحات التجميلية العمومية.\n\nمن الأفضل تفعيل هذا الخيار على الأجهزة الأقل قوة.", + "message": "خيارات تصفية المظهر العامة هي تلك الخيارات لتصفية المظهر المخصصة للتطبيق على جميع مواقع الويب. سيؤدي تفعيل هذا الخيار إلى إزالة العبء الإضافي المضاف على الذاكرة ووحدة المعالجة المركزية في صفحات الويب نتيجة للتعامل مع خيارات تصفية المظهر العامة.\nينصح بتفعيل هذا الخيار في الأجهزة الضعيفة.", "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." }, "3pSuspendUntilListsAreLoaded": { - "message": "تعليق نشاط الشبكة حتى يتم تحميل كافة قوائم عوامل التشريحات", + "message": "تعليق نشاط الشبكة حتى يتم تحميل جميع قوائم التصفية", "description": "A checkbox in the 'Filter lists' pane" }, "3pListsOfBlockedHostsHeader": { @@ -472,7 +472,7 @@ "description": "Filter lists section name" }, "3pGroupAds": { - "message": "اعلانات", + "message": "إعلانات", "description": "Filter lists section name" }, "3pGroupPrivacy": { @@ -480,15 +480,15 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "مواقع مصابة أو تحتوي على فايروسات", + "message": "الحماية من البرامج الضارة، الأمان", "description": "Filter lists section name" }, "3pGroupSocial": { - "message": "أدوات مواقع التواصل الاجتماعية", + "message": "أدوات التواصل الاجتماعي", "description": "Filter lists section name" }, "3pGroupCookies": { - "message": "اشعارات ملفات تعريف الارتباط", + "message": "إشعارات ملفات تعريف الارتباط", "description": "Filter lists section name" }, "3pGroupAnnoyances": { @@ -508,7 +508,7 @@ "description": "Filter lists section name" }, "3pImport": { - "message": "استرجاع…", + "message": "استيراد…", "description": "The label for the checkbox used to import external filter lists" }, "3pExternalListsHint": { @@ -520,7 +520,7 @@ "description": "used as a tooltip for the out-of-date icon beside a list" }, "3pViewContent": { - "message": "اظهر المحتوى", + "message": "عرض المحتوى", "description": "used as a tooltip for eye icon beside a list" }, "3pLastUpdate": { @@ -528,7 +528,7 @@ "description": "used as a tooltip for the clock icon beside a list" }, "3pUpdating": { - "message": "جار التحديث…", + "message": "تحديث…", "description": "used as a tooltip for the spinner icon beside a list" }, "3pNetworkError": { @@ -536,23 +536,23 @@ "description": "used as a tooltip for error icon beside a list" }, "1pTrustWarning": { - "message": "لا تضف مرشحات من مصادر غير موثوقة.", + "message": "لا تضف خيارات تصفية من مصادر غير موثوقة.", "description": "Warning against copy-pasting filters from random sources" }, "1pEnableMyFiltersLabel": { - "message": "مكّن تشريحاتي المخصصة", + "message": "تفعيل خيارات التصفية المخصصة لي", "description": "Label for the checkbox use to enable/disable 'My filters' list" }, "1pTrustMyFiltersLabel": { - "message": "السماح بالتشريحات المخصصة التي تتطلب الثقة", + "message": "السماح بخيارات التصفية المخصصة التي تتطلب الثقة", "description": "Label for the checkbox use to trust the content of 'My filters' list" }, "1pImport": { - "message": "استورد وألحق…", + "message": "استيراد وإلحاق…", "description": "Button in the 'My filters' pane" }, "1pExport": { - "message": "تصدير", + "message": "تصدير…", "description": "Button in the 'My filters' pane" }, "1pExportFilename": { @@ -592,11 +592,11 @@ "description": "Will discard manually-edited content and exit manual-edit mode" }, "rulesImport": { - "message": "استورد من ملف…", + "message": "استيراد من ملف…", "description": "" }, "rulesExport": { - "message": "تصدير إلى ملف", + "message": "تصدير إلى ملف…", "description": "Button in the 'My rules' pane" }, "rulesDefaultFileName": { @@ -628,19 +628,19 @@ "description": "English: a sort option for list of rules." }, "whitelistPrompt": { - "message": "تحدد توجيهات المواقع الموثوقة الصفحات التي يجب تعطيل uBlock Origin عليها. إدخال واحد في كل سطر.", + "message": "تحدد توجيهات الموقع الموثوق به صفحات الويب التي يجب تعطيل uBlock Origin عليها. أدخل رابط واحد كل سطر.", "description": "A concise description of the 'Trusted sites' pane." }, "whitelistImport": { - "message": "استورد وألحق…", + "message": "استيراد وإلحاق…", "description": "Button in the 'Trusted sites' pane" }, "whitelistExport": { - "message": "صدّر…", + "message": "تصدير…", "description": "Button in the 'Trusted sites' pane" }, "whitelistExportFilename": { - "message": "my-ublock-whitelist_{{datetime}}.txt", + "message": "my-ublock-trusted-sites_{{datetime}}.txt", "description": "The default filename to use for import/export purpose" }, "whitelistApply": { @@ -656,11 +656,11 @@ "description": "English: Domain" }, "logRequestsHeaderURL": { - "message": "رابط الموقع", + "message": "URL", "description": "English: URL" }, "logRequestsHeaderFilter": { - "message": "فلتر", + "message": "خيار تصفية", "description": "English: Filter" }, "logAll": { @@ -668,7 +668,7 @@ "description": "Appears in the logger's tab selector" }, "logBehindTheScene": { - "message": "بلا تبويب", + "message": "خلف الكواليس", "description": "Pretty name for behind-the-scene network requests" }, "loggerCurrentTab": { @@ -680,39 +680,39 @@ "description": "Tooltip for the reload button in the logger page" }, "loggerDomInspectorTip": { - "message": "بدّل فاحص DOM", + "message": "تبديل فاحص DOM", "description": "Tooltip for the DOM inspector button in the logger page" }, "loggerPopupPanelTip": { - "message": "تفعيل أو تعطيل اللوحة المنبثقة", + "message": "تبديل اللوحة المنبثقة", "description": "Tooltip for the popup panel button in the logger page" }, "loggerInfoTip": { - "message": "ويكي يو بلوك أوريجين: حافظ السجلات", + "message": "uBlock Origin wiki: السجل", "description": "Tooltip for the top-right info label in the logger page" }, "loggerClearTip": { - "message": "امسح المُسجّل", + "message": "امسح السجل", "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" }, "loggerPauseTip": { - "message": "أوقف المُسجّل مؤقتا (استبعاد كل البيانات الواردة)", + "message": "إيقاف السجل مؤقتا (تجاهل جميع البيانات الواردة)", "description": "Tooltip for the pause button in the logger page" }, "loggerUnpauseTip": { - "message": "استئناف حافظ السجلات", + "message": "استئناف السجل", "description": "Tooltip for the play button in the logger page" }, "loggerRowFiltererButtonTip": { - "message": "بدّل ترشيح المُسجّل", + "message": "تبديل تصفية السجل", "description": "Tooltip for the row filterer button in the logger page" }, "logFilterPrompt": { - "message": "رشّح محتوى السجل", + "message": "تصفية محتوى السجل", "description": "Placeholder string for logger output filtering input field" }, "loggerRowFiltererBuiltinTip": { - "message": "خيارات التصفية للمسجّل", + "message": "خيارات تصفية السجل", "description": "Tooltip for the button to bring up logger output filtering options" }, "loggerRowFiltererBuiltinNot": { @@ -724,7 +724,7 @@ "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" }, "loggerRowFiltererBuiltinBlocked": { - "message": "محظور", + "message": "محجوب", "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltinAllowed": { @@ -732,27 +732,27 @@ "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltinModified": { - "message": "معدّل", + "message": "معدل", "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltin1p": { - "message": "أول طرف ", + "message": "الطرف الأول", "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltin3p": { - "message": "ثالث-طرف ", + "message": "الطرف الثالث", "description": "A keyword in the built-in row filtering expression" }, "loggerEntryDetailsHeader": { - "message": "تفاصيل", + "message": "التفاصيل", "description": "Small header to identify the 'Details' pane for a specific logger entry" }, "loggerEntryDetailsFilter": { - "message": "المرشّح", + "message": "خيار تصفية", "description": "Label to identify a filter field" }, "loggerEntryDetailsFilterList": { - "message": "قائمة المرشحات", + "message": "قائمة خيارات التصفية", "description": "Label to identify a filter list field" }, "loggerEntryDetailsRule": { @@ -764,11 +764,11 @@ "description": "Label to identify a context field (typically a hostname)" }, "loggerEntryDetailsRootContext": { - "message": "سياق الجدر", + "message": "سياق الجذر", "description": "Label to identify a root context field (typically a hostname)" }, "loggerEntryDetailsPartyness": { - "message": "عديمة الطرف", + "message": "حالة الطرف", "description": "Label to identify a field providing partyness information" }, "loggerEntryDetailsType": { @@ -792,7 +792,7 @@ "description": "Label for the type selector" }, "loggerStaticFilteringHeader": { - "message": "فلتر ثابت", + "message": "خيار تصفية ثابت", "description": "Small header to identify the static filtering section" }, "loggerStaticFilteringSentence": { @@ -832,35 +832,35 @@ "description": "Used in the static filtering wizard" }, "loggerStaticFilteringFinderSentence1": { - "message": "تصفية ثابتة {{filter}} موجود في:", + "message": "تم العثور على خيار تصفية ثابت {{filter}} في:", "description": "Below this sentence, the filter list(s) in which the filter was found" }, "loggerStaticFilteringFinderSentence2": { - "message": "الترشيح الثابت لا يوجد في أي من قوائم التشريحات المفعلة", + "message": "تعذر العثور على خيار التصفية الثابت في أي من قوائم خيارات التصفية المفعلة حاليا", "description": "Message to show when a filter cannot be found in any filter lists" }, "loggerSettingDiscardPrompt": { - "message": "مدخلات المُسجّل التي لا تطابق أيا من المعايير ستتجاهل تلقائيا:", + "message": "إدخالات السجل التي لا تستوفي جميع الشروط الثلاثة أدناه سيتم تجاهلها تلقائيا:", "description": "Logger setting: A sentence to describe the purpose of the settings below" }, "loggerSettingPerEntryMaxAge": { - "message": "أبق على المدخلات في آخر {{input}} دقيقة", + "message": "الاحتفاظ بالإدخالات من آخر {{input}} دقائق", "description": "A logger setting" }, "loggerSettingPerTabMaxLoads": { - "message": "أبقِ بحد أقصى على {{input}} تحميلات للصفحة في كل لسان", + "message": "الاحتفاظ بـ {{input}} من عمليات تحميل الصفحات كحد أقصى لكل علامة تبويب", "description": "A logger setting" }, "loggerSettingPerTabMaxEntries": { - "message": "أبق بحد أقصى على {{input}} مدخلات في كل لسان", + "message": "الاحتفاظ بـ {{input}} من الإدخالات كحد أقصى لكل علامة تبويب", "description": "A logger setting" }, "loggerSettingPerEntryLineCount": { - "message": "استخدم {{input}} من السطور لكل مدخلة في الوضع الرأسي", + "message": "استخدام {{input}} أسطر لكل إدخال في وضع التوسيع العمودي", "description": "A logger setting" }, "loggerSettingHideColumnsPrompt": { - "message": "أخفِ الأعمدة:", + "message": "إخفاء الأعمدة:", "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" }, "loggerSettingHideColumnTime": { @@ -868,7 +868,7 @@ "description": "A label for the time column" }, "loggerSettingHideColumnFilter": { - "message": "{{input}} المرشِّح\\القاعدة", + "message": "{{input}} خيار التصفية/القاعدة", "description": "A label for the filter or rule column" }, "loggerSettingHideColumnContext": { @@ -876,7 +876,7 @@ "description": "A label for the context column" }, "loggerSettingHideColumnPartyness": { - "message": "{{input}} الجهة", + "message": "{{input}} حالة الطرف", "description": "A label for the partyness column" }, "loggerExportFormatList": { @@ -888,7 +888,7 @@ "description": "Label for radio-button to pick export format" }, "loggerExportEncodePlain": { - "message": "واضح", + "message": "نص عادي", "description": "Label for radio-button to pick export text format" }, "loggerExportEncodeMarkdown": { @@ -900,19 +900,19 @@ "description": "Text for button which open an external web page in Support pane" }, "supportReportSpecificButton": { - "message": "إنشاء تقرير جديد", + "message": "إنشاء تقرير جديد علي GitHub", "description": "Text for button which open an external web page in Support pane" }, "supportFindSpecificButton": { - "message": "العثور على تقارير مماثلة", + "message": "العثور على تقارير مماثلة على GitHub", "description": "A clickable link in the filter issue reporter section" }, "supportS1H": { - "message": "وثائق", + "message": "التوثيق", "description": "Header of 'Documentation' section in Support pane" }, "supportS1P1": { - "message": "اقرأ الوثائق الموجودة في uBlock/wiki للتعرف على جميع ميزات uBlock Origin.", + "message": "اقرأ التوثيق في uBlock/wiki للتعرف على جميع ميزات uBlock Origin.", "description": "First paragraph of 'Documentation' section in Support pane" }, "supportS2H": { @@ -920,15 +920,15 @@ "description": "Header of 'Questions and support' section in Support pane" }, "supportS2P1": { - "message": "يتم توفير إجابات للأسئلة وأنواع أخرى من دعم المساعدة على subreddit /r/uBlockOrigin/r/uBlockOrigin.", "description": "First paragraph of 'Questions and support' section in Support pane" }, "supportS3H": { - "message": "تشريح المسائل/موقع الويب معطوب", + "message": "مشكلات في خيارات التصفية/الموقع معطل", "description": "Header of 'Filter issues' section in Support pane" }, "supportS3P1": { - "message": "أبلغ عن مشكلات التصفية مع مواقع ويب معينة إلى uBlockOrigin/uAssets issue tracker. يتطلب حساب GitHub.", + "message": "الإبلاغ عن مشكلات خيارات التصفية في مواقع ويب معينة uBlockOrigin/uAssetsاداة تعقب المشكلات.\nيتطلب حساب GitHub.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS3P2": { @@ -936,7 +936,7 @@ "description": "Second paragraph of 'Filter issues' section in Support pane" }, "supportS3P3": { - "message": "نصائح: تأكد من تحديث قوائم التصفية. المُسجِّل هو الأداة الأساسية لتشخيص المشكلات المتعلقة بالفلتر.", + "message": "نصائح: تأكد من أن قوائم خيارات التصفية لديك محدثة. يعد السجل الأداة الأساسية لتشخيص المشكلات المتعلقة بخيارات التصفية.", "description": "Third paragraph of 'Filter issues' section in Support pane" }, "supportS4H": { @@ -944,31 +944,31 @@ "description": "Header of 'Bug report' section in Support pane" }, "supportS4P1": { - "message": "الإبلاغ عن المشكلات المتعلقة بيو بلوك أوريجين نفسه إلى uBlockOrigin/uBlock-issue أداة تعقب المشكلات. يتطلب حساب GitHub", + "message": "الإبلاغ عن المشكلات المتعلقة بـ uBlock Origin نفسه إلى uBlockOrigin/uBlock-issue أداة تعقب المشكلات. \nيتطلب حساب GitHub", "description": "First paragraph of 'Bug report' section in Support pane" }, "supportS5H": { - "message": "رأس قسم \"معلومات استكشاف الأخطاء وإصلاحها\" في جزء الدعم", + "message": "معلومات استكشاف الأخطاء وإصلاحها", "description": "Header of 'Troubleshooting Information' section in Support pane" }, "supportS5P1": { - "message": "فيما يلي معلومات فنية قد تكون مفيدة عندما يحاول المتطوعون مساعدتك في حل مشكلة ما.فيما يلي معلومات فنية قد تكون مفيدة عندما يحاول المتطوعون مساعدتك في حل مشكلة ما. ", + "message": "فيما يلي معلومات تقنية قد تكون مفيدة عندما يحاول المتطوعون مساعدتك في حل مشكلة ما.", "description": "First paragraph of 'Troubleshooting Information' section in Support pane" }, "supportS6H": { - "message": "الإبلاغ عن مشكلة في عوامل التصفية", + "message": "الإبلاغ عن مشكلة في خيارات التصفية", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "لتجنب إثقال كاهل المتطوعين بتقارير مكررة، يرجى التحقق من عدم الإبلاغ عن المشكلة بالفعل.", + "message": "لتجنب إنهاك المتطوعين بتقارير مكررة، يرجى التأكد من أن المشكلة لم يتم الإبلاغ عنها من قبل.ملاحظة: النقر على الزر سيؤدي إلى إرسال أصل الصفحة إلى موقع GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { - "message": "يتم تحديث قوائم الفلتر بشكل يومي. تحقق أن مشكلتك لم يتم مواجهتها في أحدث قوائم الفلتر.", + "message": "تحدث قوائم خيارات التصفية يوميا. تأكد من أن مشكلتك لم يتم حلها بالفعل في أحدث قوائم خيارات التصفية.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S2": { - "message": "تحقق من أن المشكلة ما تزال موجودة بعد إعادة تحميل صفحة الويب التي بها إشكالية.", + "message": "تحقق من أن المشكلة لا تزل قائمة بعد إعادة تحميل صفحة الويب المعنية.", "description": "A paragraph in the filter issue reporter section" }, "supportS6URL": { @@ -980,39 +980,39 @@ "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- إختر خيارًا --", + "message": "— اختر إدخالا —", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "ٌيُظهر الإعلانات أو بقايا الإعلانات", + "message": "يعرض إعلانات أو بقايا إعلانات", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "به تراكبات أو مضايقات أخرى", + "message": "يحتوي على طبقات تداخل أو عوائق أخرى", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "يكتشف يو بلوك أوريجين", + "message": "يكتشف uBlock Origin", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "توجد مشكلات متعلقة بالخصوصية", + "message": "تنطوي على مشكلات تتعلق بالخصوصية", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "أعطال عند تمكين uBlock Origin", + "message": "يحدث خلل وظيفي عندما يكون uBlock Origin مفعلا", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "افتح التبويبات أو النوافذ التي ليس مرغوبًا بها", + "message": "يفتح علامات تبويب أو نوافذ غير مرغوب فيها", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "يؤدي إلى البرامج الضارة والإحتيال", + "message": "يؤدي إلى البرمجيات الضارة والاحتيال", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "ضع علامة على صفحة الويب بـ ”NSFW“ (”غير آمن للعمل“)", + "message": "ضع علامة على صفحة الويب بـ ”NSFW“ (”غير آمنة للعمل“)", "description": "A checkbox to use for NSFW sites" }, "aboutPrivacyPolicy": { @@ -1024,7 +1024,7 @@ "description": "" }, "aboutCode": { - "message": "اكواد البرنامج (GPLv3)", + "message": "كود المصدر (GPLv3)", "description": "English: Source code (GPLv3)" }, "aboutContributors": { @@ -1032,7 +1032,7 @@ "description": "English: Contributors" }, "aboutSourceCode": { - "message": "شيفرة المصدر", + "message": "كود المصدر", "description": "Link text to source code repo" }, "aboutTranslations": { @@ -1040,31 +1040,31 @@ "description": "Link text to translations repo" }, "aboutFilterLists": { - "message": "القوائم المرشحة", + "message": "قوائم خيارات التصفية", "description": "Link text to uBO's own filter lists repo" }, "aboutDependencies": { - "message": "الإعتماديات الخارجية (متوافقة مع GPLv3):", + "message": "التبعيات الخارجية (متوافقة مع GPLv3):", "description": "Shown in the About pane" }, "aboutCDNs": { - "message": "قوائم التصفية الخاصة بـ uBO مستضافة مجانًا على CDNs التالية:", + "message": "يتم استضافة قوائم التصفية الخاصة بـ uBO مجانا على المواقع التالية CDNs:", "description": "Shown in the About pane" }, "aboutCDNsInfo": { - "message": "يتم استخدام CDN الذي تم اختياره عشوائيًا عند الحاجة إلى تحديث قائمة عوامل التصفية.", + "message": "تستخدم شبكة توصيل محتوى CDN عشوائية عندما تحتاج قائمة خيارات التصفية إلى تحديث.", "description": "Shown in the About pane" }, "aboutBackupDataButton": { - "message": "النسخ الإحتياطي إلى ملف…", + "message": "نسخ احتياطي إلى ملف…", "description": "Text for button to create a backup of all settings" }, "aboutBackupFilename": { - "message": "إحتياط-ublock-الخاص-بي_{{datetime}}.txt", + "message": "نسخة-احتياطية-ublock-الخاص-بي_{{datetime}}.txt", "description": "English: my-ublock-backup_{{datetime}}.txt" }, "aboutRestoreDataButton": { - "message": "إسترجع من الملف…", + "message": "استعادة من ملف…", "description": "English: Restore from file..." }, "aboutResetDataButton": { @@ -1072,7 +1072,7 @@ "description": "English: Reset to default settings..." }, "aboutRestoreDataConfirm": { - "message": "كل إعداداتك سوف يتم كتابتها بإستعمال البيانات التي تم نسخها إحتياطيا على {{time}}، و سيعيد uBlock₀ التشغيل.\n\nأعد كتابة كل الإعدادات الموجود بإستخدام البيانات التي تم نسخها إحتياطيا؟", + "message": "كل إعداداتك سوف يتم كتابتها باستعمال البيانات التي تم نسخها احتياطيا على {{time}}، و سيعيد uBlock₀ التشغيل.\n\nأعد كتابة كل الإعدادات الموجود باستخدام البيانات التي تم نسخها احتياطيا؟", "description": "Message asking user to confirm restore" }, "aboutRestoreDataError": { @@ -1124,7 +1124,7 @@ "description": "Firefox/Fennec-specific: Show Logger" }, "fennecMenuItemBlockingOff": { - "message": "تعطيل", + "message": "إيقاف", "description": "Firefox-specific: appears as 'uBlock₀ (off)'" }, "docblockedTitle": { @@ -1132,11 +1132,11 @@ "description": "Used as a title for the document-blocked page" }, "docblockedPrompt1": { - "message": "uBlock₀ منع الصفحة التالية من التحميل:", + "message": "لقد منع uBlock Origin تحميل الصفحة التالية:", "description": "Used in the strict-blocking page" }, "docblockedPrompt2": { - "message": "بسبب الفلتر التالي", + "message": "حدث هذا بسبب خيار التصفية التالي:", "description": "Used in the strict-blocking page" }, "docblockedNoParamsPrompt": { @@ -1156,7 +1156,7 @@ "description": "English: Close this window" }, "docblockedDontWarn": { - "message": "لا تحذرني مرة أخرى بشأن هذا الموقع", + "message": "لا تحذرني مجددا بشأن هذا الموقع", "description": "Label for checkbox in document-blocked page" }, "docblockedProceed": { @@ -1172,11 +1172,11 @@ "description": "English: Permanently" }, "docblockedDisable": { - "message": "تقدّم", + "message": "متابعة", "description": "Button text to navigate to the blocked page" }, "docblockedRedirectPrompt": { - "message": "الصفحة المحظورة تريد إعادة توجيهك إلى موقع آخر. إذا اخترت المتابعة، فسوف تنتقل مباشرة إلى: {{url}}", + "message": "تريد الصفحة المحجوبة إعادة توجيهك إلى موقع آخر. إذا اخترت المتابعة، فستنتقل مباشرة إلى: {{url}}", "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { @@ -1184,11 +1184,11 @@ "description": "The label which prepend the actual reason why a page was blocked" }, "docblockedReasonMalicious": { - "message": "ضار", + "message": "برنامج خبيث", "description": "An actual reason why a page was blocked" }, "docblockedReasonTracker": { - "message": "متتبع", + "message": "أداة تتبع", "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { @@ -1208,7 +1208,7 @@ "description": "tooltip" }, "cloudNoData": { - "message": "...\n...", + "message": "…\n…", "description": "" }, "cloudDeviceNamePrompt": { @@ -1236,11 +1236,11 @@ "description": "" }, "contextMenuBlockElementInFrame": { - "message": "احظر العنصر في الإطار…", + "message": "حجب العنصر في الإطار…", "description": "An entry in the browser's contextual menu" }, "contextMenuSubscribeToList": { - "message": "اشترك في قائمة التصفية…", + "message": "اشترك في قائمة خيارات التصفية…", "description": "An entry in the browser's contextual menu" }, "contextMenuTemporarilyAllowLargeMediaElements": { @@ -1252,11 +1252,11 @@ "description": "A context menu entry, to view the source code of the target resource" }, "shortcutCapturePlaceholder": { - "message": "أدخِل اختصار", + "message": "اضغط على مفاتيح الاختصار", "description": "Placeholder string for input field used to capture a keyboard shortcut" }, "genericMergeViewScrollLock": { - "message": "بدل حالة التمرير الموصَد", + "message": "تبديل التمرير المقفل", "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" }, "genericCopyToClipboard": { @@ -1268,15 +1268,15 @@ "description": "Label for buttons used to select all text in editor" }, "toggleCosmeticFiltering": { - "message": "تبديل تصفية مستحضرات التجميل", + "message": "تبديل تصفية المظهر", "description": "Label for keyboard shortcut used to toggle cosmetic filtering" }, "toggleJavascript": { - "message": "تعطيل جافا سكريبت", + "message": "تبديل جافا سكريبت", "description": "Label for keyboard shortcut used to toggle no-scripting switch" }, "relaxBlockingMode": { - "message": "وضع الحظر المتراخي", + "message": "تخفيف وضع الحجب", "description": "Label for keyboard shortcut used to relax blocking mode" }, "storageUsed": { @@ -1284,27 +1284,27 @@ "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" }, "KB": { - "message": "كيلوبايت", + "message": "KB", "description": "short for 'kilobytes'" }, "MB": { - "message": "ميجابايت", + "message": "MB", "description": "short for 'megabytes'" }, "GB": { - "message": "جيجابايت", + "message": "GB", "description": "short for 'gigabytes'" }, "clickToLoad": { - "message": "اضغط للتحميل", + "message": "انقر للتحميل", "description": "Message used in frame placeholders" }, "linterMainReport": { - "message": "أخطاء: {{count}}", + "message": "الأخطاء: {{count}}", "description": "Summary of number of errors as reported by the linter " }, "unprocessedRequestTooltip": { - "message": "لا يمكن الفلترة بشكل صحيح عند تشغيل المتصفح.\nقم بتحديث الصفحة للتأكد من الفلترة بشكل صحيح.", + "message": "تعذر إجراء التصفية بشكل صحيح عند تشغيل المتصفح. أعد تحميل الصفحة لضمان التصفية الصحيحة.", "description": "A warning which will appear in the popup panel if needed" }, "dummy": { diff --git a/src/_locales/az/messages.json b/src/_locales/az/messages.json index d95a39b18b702..df1f4e7e7b782 100644 --- a/src/_locales/az/messages.json +++ b/src/_locales/az/messages.json @@ -4,7 +4,7 @@ "description": "extension name." }, "extShortDesc": { - "message": "Axır ki, prosessor və yaddaş yükünü azaldan səmərəli bir əngəlləyici var.", + "message": "Nəhayət, səmərəli bloklayıcı. Prosessor və yaddaşı yükləmir.", "description": "this will be in the Chrome web store: must be 132 characters or less" }, "dashboardName": { @@ -12,15 +12,15 @@ "description": "English: uBlock₀ — Dashboard" }, "dashboardUnsavedWarning": { - "message": "Xəbərdarlıq: dəyişiklikləriniz yadda saxlanılmayıb!", + "message": "Xəbərdarlıq! Saxlamadığınız dəyişikliklər var", "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "Qal", + "message": "Burada qal", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { - "message": "Əhəmiyyət vermə", + "message": "Məhəl qoyma", "description": "Label for button to ignore unsaved changes" }, "settingsPageName": { @@ -48,7 +48,7 @@ "description": "appears as tab name in dashboard" }, "statsPageName": { - "message": "uBlock₀ — Jurnal", + "message": "uBlock₀ — Qeydiyyat jurnalı", "description": "Title for the logger window" }, "aboutPageName": { @@ -60,7 +60,7 @@ "description": "appears as tab name in dashboard" }, "assetViewerPageName": { - "message": "uBlock₀ — Resurslar", + "message": "uBlock₀ — Resurs baxıcısı", "description": "Title for the asset viewer page" }, "advancedSettingsPageName": { @@ -68,19 +68,19 @@ "description": "Title for the advanced settings page" }, "popupPowerSwitchInfo": { - "message": "Klikləmə: Bu sayt üçün uBlock₀-u fəallaşdır/sıradan çıxart.\n\nCtrl+klikləmə: Yalnız bu səhifə üçün uBlock₀-u sıradan çıxart.", + "message": "Klikləmə: uBlock₀-u bu sayt üçün qapadın/aktivləşdirin.\n\n​Ctrl+klikləmə: uBlock₀-u yalnız bu səhifədə qapadın.", "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." }, "popupPowerSwitchInfo1": { - "message": "Bu sayt üçün uBlock₀-u sıradan çıxartmaq üçün klikləyin.\n\nYalnız bu səhifə üçün uBlock₀-u sıradan çıxartmaq üçün Ctrl+klikləyin.", + "message": "Bu sayt üçün uBlock₀-u qapatmaq məqsədilə klikləyin.\n\nYalnız bu səhifədə uBlock₀-u qapatmaq məqsədilə Ctrl+klikləyin.", "description": "Message to be read by screen readers" }, "popupPowerSwitchInfo2": { - "message": "Bu saytda uBlock₀-u fəallaşdırmaq üçün klikləyin.", + "message": "Bu sayt üçün uBlock₀-u aktivləşdirmək məqsədilə klikləyin.", "description": "Message to be read by screen readers" }, "popupBlockedRequestPrompt": { - "message": "tələb(request) bloklandı", + "message": "bloklanmış sorğular", "description": "English: requests blocked" }, "popupBlockedOnThisPagePrompt": { @@ -88,11 +88,11 @@ "description": "English: on this page" }, "popupBlockedStats": { - "message": "{{count}} və ya {{percent}}%", + "message": "{{count}} ({{percent}}%)", "description": "Example: 15 (13%)" }, "popupBlockedSinceInstallPrompt": { - "message": "quraşdırmadan bəri", + "message": "quraşdırılandan bəri", "description": "English: since install" }, "popupOr": { @@ -100,15 +100,15 @@ "description": "English: or" }, "popupBlockedOnThisPage_v2": { - "message": "Bu səhifədə əngəllənən", + "message": "Bu səhifədə əngəllənmiş", "description": "For the new mobile-friendly popup design" }, "popupBlockedSinceInstall_v2": { - "message": "Quraşdırmadan bəri əngəllənən", + "message": "Quraşdırılandan bəri bloklanıb", "description": "For the new mobile-friendly popup design" }, "popupDomainsConnected_v2": { - "message": "Bağlantı qurulmuş domenlər", + "message": "Qoşulmuş domenlər", "description": "For the new mobile-friendly popup design" }, "popupTipDashboard": { @@ -116,7 +116,7 @@ "description": "English: Click to open the dashboard" }, "popupTipZapper": { - "message": "Element silmə rejiminə keç", + "message": "Element təmizləyicisi rejiminə keç", "description": "Tooltip for the element-zapper icon in the popup panel" }, "popupTipPicker": { @@ -124,7 +124,7 @@ "description": "English: Enter element picker mode" }, "popupTipLog": { - "message": "Jurnalı aç", + "message": "Qeydiyyat jurnalını aç", "description": "Tooltip used for the logger icon in the panel" }, "popupTipReport": { @@ -132,7 +132,7 @@ "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipNoPopups": { - "message": "Bu sayt üçün bütün açılan pəncələri aç/bağla", + "message": "​Bu sayt üçün bütün açılan pəncərələrin bloklanmasını tənzimlə", "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoPopups1": { @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Lokal qaydalar: bu sütun yalnız bu saytda tətbiq olunan qaydalar üçündür.\nLokal qaydalar qlobal qaydalardan üstün tutulur.", + "message": "Lokal qaydalar: bu sütun yalnız bu saytda tətbiq olunan qaydalar üçündür.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -340,7 +340,7 @@ "description": "Section for controlling user interface appearance" }, "settingsThemeLabel": { - "message": "Mövzu", + "message": "Tema", "description": "Label for checkbox to enable a custom dark theme" }, "settingsThemeAccent0Label": { @@ -404,7 +404,7 @@ "description": "Section for controlling advanced-user settings" }, "settingsAdvancedSynopsis": { - "message": "Yalnız texniki istifadəçilərə uyğun parametrlər", + "message": "Yalnız təcrübəli istifadəçilər üçün nəzərdə tutulmuş funksiyalar", "description": "Description of section controlling advanced-user settings" }, "settingsAdvancedUserSettings": { @@ -456,7 +456,7 @@ "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." }, "3pSuspendUntilListsAreLoaded": { - "message": "Filter siyahıları yüklənənə kimi şəbəkə fəaliyyətini dayandır", + "message": "Filtr siyahıları yüklənənə kimi şəbəkə fəaliyyətini dayandır", "description": "A checkbox in the 'Filter lists' pane" }, "3pListsOfBlockedHostsHeader": { @@ -472,7 +472,7 @@ "description": "Filter lists section name" }, "3pGroupAds": { - "message": "Reklam", + "message": "Reklamlar", "description": "Filter lists section name" }, "3pGroupPrivacy": { @@ -480,7 +480,7 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "Zərərli domenlər", + "message": "Zərərli proqram təminatından qorunma, təhlükəsizlik", "description": "Filter lists section name" }, "3pGroupSocial": { @@ -528,7 +528,7 @@ "description": "used as a tooltip for the clock icon beside a list" }, "3pUpdating": { - "message": "Yenilənir...", + "message": "Yenilənir…", "description": "used as a tooltip for the spinner icon beside a list" }, "3pNetworkError": { @@ -908,7 +908,7 @@ "description": "A clickable link in the filter issue reporter section" }, "supportS1H": { - "message": "Dokumentasiya", + "message": "Sənədləşmə", "description": "Header of 'Documentation' section in Support pane" }, "supportS1P1": { @@ -924,7 +924,7 @@ "description": "First paragraph of 'Questions and support' section in Support pane" }, "supportS3H": { - "message": "Filter problemləri / vebsəhifə işləmir", + "message": "Filtr problemləri / veb sayt işləmir", "description": "Header of 'Filter issues' section in Support pane" }, "supportS3P1": { @@ -952,7 +952,7 @@ "description": "Header of 'Troubleshooting Information' section in Support pane" }, "supportS5P1": { - "message": "Aşağıdaki könüllülər sizə probleminizi aradan qaldırmağa çalışırkən faydalı ola biləcək texniki məlumatdır.", + "message": "Aşağıda köməkçilər sizə kömək etmək üçün problemi həll etməyə çalışarkən faydalı ola biləcək texniki məlumatlar verilmişdir.", "description": "First paragraph of 'Troubleshooting Information' section in Support pane" }, "supportS6H": { @@ -976,7 +976,7 @@ "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "Səhifə...", + "message": "Səhifə…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { @@ -1056,7 +1056,7 @@ "description": "Shown in the About pane" }, "aboutBackupDataButton": { - "message": "Fayla yaz", + "message": "Fayla yaz…", "description": "Text for button to create a backup of all settings" }, "aboutBackupFilename": { @@ -1064,11 +1064,11 @@ "description": "English: my-ublock-backup_{{datetime}}.txt" }, "aboutRestoreDataButton": { - "message": "Fayldan bərpa et...", + "message": "Fayldan bərpa et…", "description": "English: Restore from file..." }, "aboutResetDataButton": { - "message": "Standart parametrləri yüklə...", + "message": "Standart parametrləri yüklə…", "description": "English: Reset to default settings..." }, "aboutRestoreDataConfirm": { @@ -1236,11 +1236,11 @@ "description": "" }, "contextMenuBlockElementInFrame": { - "message": "Çərçivədəki elementi əngəllə", + "message": "Çərçivədəki elementi əngəllə…", "description": "An entry in the browser's contextual menu" }, "contextMenuSubscribeToList": { - "message": "Filter siyahısına abunə ol", + "message": "Filter siyahısına abunə ol…", "description": "An entry in the browser's contextual menu" }, "contextMenuTemporarilyAllowLargeMediaElements": { @@ -1248,7 +1248,7 @@ "description": "A context menu entry, present when large media elements have been blocked on the current site" }, "contextMenuViewSource": { - "message": "Mənbə kodunu nəzərdən keçir...", + "message": "Mənbə kodunu nəzərdən keçir…", "description": "A context menu entry, to view the source code of the target resource" }, "shortcutCapturePlaceholder": { diff --git a/src/_locales/be/messages.json b/src/_locales/be/messages.json index 11a9c39b62bd4..0e0910d8289a5 100644 --- a/src/_locales/be/messages.json +++ b/src/_locales/be/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Лакальныя правілы: гэты слупок для правіл, якія прымяняюцца толькі на гэтым сайце.\nЛакальныя правілы перавызначаюць глабальныя.", + "message": "Лакальныя правілы: гэты слупок для правіл, якія прымяняюцца толькі на гэтым сайце.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -480,7 +480,7 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "Дамены шкодных праграм", + "message": "Абарона ад шкоднасных праграм, бяспека", "description": "Filter lists section name" }, "3pGroupSocial": { @@ -548,11 +548,11 @@ "description": "Label for the checkbox use to trust the content of 'My filters' list" }, "1pImport": { - "message": "Імпартаваць і дадаць", + "message": "Імпартаваць і дадаць…", "description": "Button in the 'My filters' pane" }, "1pExport": { - "message": "Экспартаваць", + "message": "Экспартаваць…", "description": "Button in the 'My filters' pane" }, "1pExportFilename": { @@ -596,7 +596,7 @@ "description": "" }, "rulesExport": { - "message": "Экспартаваць у файл", + "message": "Экспартаваць у файл…", "description": "Button in the 'My rules' pane" }, "rulesDefaultFileName": { @@ -632,11 +632,11 @@ "description": "A concise description of the 'Trusted sites' pane." }, "whitelistImport": { - "message": "Імпартаваць і дадаць", + "message": "Імпартаваць і дадаць…", "description": "Button in the 'Trusted sites' pane" }, "whitelistExport": { - "message": "Экспартаваць", + "message": "Экспартаваць…", "description": "Button in the 'Trusted sites' pane" }, "whitelistExportFilename": { @@ -672,7 +672,7 @@ "description": "Pretty name for behind-the-scene network requests" }, "loggerCurrentTab": { - "message": "Дзейная картка", + "message": "Бягучая ўкладка", "description": "Appears in the logger's tab selector" }, "loggerReloadTip": { @@ -900,11 +900,11 @@ "description": "Text for button which open an external web page in Support pane" }, "supportReportSpecificButton": { - "message": "Стварыць новую справаздачу", + "message": "Стварыць новую справаздачу на GitHub", "description": "Text for button which open an external web page in Support pane" }, "supportFindSpecificButton": { - "message": "Знайсці падобныя справаздачы", + "message": "Знайсці падобныя справаздачы на GitHub", "description": "A clickable link in the filter issue reporter section" }, "supportS1H": { @@ -960,7 +960,7 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "Каб не абцяжарваць добраахвотнікаў дубляванымі справаздачамі, калі ласка, праверце, што пра гэтую праблему не паведамлялі раней.", + "message": "Каб не абцяжарваць добраахвотнікаў дубляванымі справаздачамі, праверце, ці не паведамлялі пра гэтую праблему раней. Заўвага: націсканне кнопкі прывядзе да адпраўкі паходжання старонкі на GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { @@ -1100,7 +1100,7 @@ "description": "English: {{value}} minutes ago" }, "elapsedOneHourAgo": { - "message": "гадзіну таму назад", + "message": "гадзіну таму", "description": "English: an hour ago" }, "elapsedManyHoursAgo": { @@ -1136,7 +1136,7 @@ "description": "Used in the strict-blocking page" }, "docblockedPrompt2": { - "message": "З-за наступнага фільтра", + "message": "Гэта адбылося з-за наступнага фільтра:", "description": "Used in the strict-blocking page" }, "docblockedNoParamsPrompt": { @@ -1144,7 +1144,7 @@ "description": "label to be used for the parameter-less URL: https://cloud.githubusercontent.com/assets/585534/9832014/bfb1b8f0-593b-11e5-8a27-fba472a5529a.png" }, "docblockedFoundIn": { - "message": "Знойдзены ў:", + "message": "Фільтр быў знойдзены ў:", "description": "English: List of filter list names follows" }, "docblockedBack": { diff --git a/src/_locales/bg/messages.json b/src/_locales/bg/messages.json index 2ebcd88826236..213886eb901d2 100644 --- a/src/_locales/bg/messages.json +++ b/src/_locales/bg/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Локални правила: колона с правила, приложими само към текущият сайт. Локалните правила заместват глобалните.", + "message": "Локални правила: колона с правила, приложими само към текущият сайт.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { diff --git a/src/_locales/bn/messages.json b/src/_locales/bn/messages.json index 1e9c995815196..058dbc26505af 100644 --- a/src/_locales/bn/messages.json +++ b/src/_locales/bn/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "অভ্যন্তরীন নিয়ম: এই কলামটি সেইসব নিয়মের জন্য যা শুধু বর্তমান সাইটে প্রয়োগ করা হবে।\nঅভ্যন্তরীন নিয়ম সার্বজনীন নিয়মকে অগ্রাহ্য করবে।", + "message": "অভ্যন্তরীন নিয়ম: এই কলামটি সেইসব নিয়মের জন্য যা শুধু বর্তমান সাইটে প্রয়োগ করা হবে।", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { diff --git a/src/_locales/br_FR/messages.json b/src/_locales/br_FR/messages.json index a08dbb0a5c5f2..4207b6e7dfdd6 100644 --- a/src/_locales/br_FR/messages.json +++ b/src/_locales/br_FR/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Reolennoù lec'hel: er bann-mañ e vez lakaet ar reolennoù ne dalvezont nemet d'al lec'hienn m'emaoc'h.\nAr reolennoù lec'hel a ya a-raok ar reolennoù hollek.", + "message": "Reolennoù lec'hel: er bann-mañ e vez lakaet ar reolennoù ne dalvezont nemet d'al lec'hienn m'emaoc'h.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -960,7 +960,7 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "Evit nompas sammañ ar genlabourerien a-youl vat gant meur a zanevell heñvel, gwiriit ma n'eo ket bet danevellet ho kudenn en a-raok mar plij.", + "message": "Evit nompas sammañ ar genlabourerien a-youl vat gant meur a zanevell heñvel, gwiriit ma n'eo ket bet danevellet ho kudenn en a-raok mar plij. Notenn: ma klikit ar bouton e vo kaset anv herberc'hier ar bajenn da c'h-GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { diff --git a/src/_locales/bs/messages.json b/src/_locales/bs/messages.json index d4303e9071fe7..803877f7db4b5 100644 --- a/src/_locales/bs/messages.json +++ b/src/_locales/bs/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Lokalna pravila: ovaj stupac je za pravila koja su primjenjena samo za ovaj sajt.\nLokalna pravila nadglasaju globalna pravila.", + "message": "Lokalna pravila: ovaj stupac je za pravila koja su primjenjena samo za ovaj sajt.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -480,7 +480,7 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "Zlonamjerne domene", + "message": "Zaštita od zlonamjernog softvera, sigurnost", "description": "Filter lists section name" }, "3pGroupSocial": { @@ -960,7 +960,7 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "Da bi ste izbjegli opterećivanje dobrovoljaca sa dupliciranim prijavama, molimo vas da provjerite da li je vaš problem već prijavljen, ili nije.", + "message": "Kako biste izbjegli opterećivanje volontera duplim prijavama, molimo vas da provjerite da problem već nije prijavljen. Napomena: klikom na dugme, porijeklo stranice će biti poslano GitHubu.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { diff --git a/src/_locales/ca/messages.json b/src/_locales/ca/messages.json index f342572b35c96..6f9aa9c647d07 100644 --- a/src/_locales/ca/messages.json +++ b/src/_locales/ca/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Regles locals: les regles d'aquesta columna s'apliquen només al lloc actual.\nLes regles locals anul·len les regles globals.", + "message": "Regles locals: les regles d'aquesta columna s'apliquen només al lloc actual.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { diff --git a/src/_locales/cs/messages.json b/src/_locales/cs/messages.json index 3c722c28715be..c6511e51e0c52 100644 --- a/src/_locales/cs/messages.json +++ b/src/_locales/cs/messages.json @@ -312,7 +312,7 @@ "description": "English: Click, Ctrl-click" }, "pickerContextMenuEntry": { - "message": "Zablokovat prvek...", + "message": "Zablokovat prvek…", "description": "An entry in the browser's contextual menu" }, "settingsCollapseBlockedPrompt": { @@ -480,7 +480,7 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "Ochrana před malwarem, bezpečnost", + "message": "Ochrana před malwarem, zabezpečení", "description": "Filter lists section name" }, "3pGroupSocial": { @@ -508,7 +508,7 @@ "description": "Filter lists section name" }, "3pImport": { - "message": "Importovat...", + "message": "Importovat…", "description": "The label for the checkbox used to import external filter lists" }, "3pExternalListsHint": { @@ -528,7 +528,7 @@ "description": "used as a tooltip for the clock icon beside a list" }, "3pUpdating": { - "message": "Aktualizování...", + "message": "Aktualizování…", "description": "used as a tooltip for the spinner icon beside a list" }, "3pNetworkError": { @@ -548,11 +548,11 @@ "description": "Label for the checkbox use to trust the content of 'My filters' list" }, "1pImport": { - "message": "Importovat a připojit...", + "message": "Importovat a připojit…", "description": "Button in the 'My filters' pane" }, "1pExport": { - "message": "Exportovat...", + "message": "Exportovat…", "description": "Button in the 'My filters' pane" }, "1pExportFilename": { @@ -592,11 +592,11 @@ "description": "Will discard manually-edited content and exit manual-edit mode" }, "rulesImport": { - "message": "Importovat ze souboru...", + "message": "Importovat ze souboru…", "description": "" }, "rulesExport": { - "message": "Exportovat do souboru...", + "message": "Exportovat do souboru…", "description": "Button in the 'My rules' pane" }, "rulesDefaultFileName": { @@ -632,11 +632,11 @@ "description": "A concise description of the 'Trusted sites' pane." }, "whitelistImport": { - "message": "Importovat a připojit...", + "message": "Importovat a připojit…", "description": "Button in the 'Trusted sites' pane" }, "whitelistExport": { - "message": "Exportovat...", + "message": "Exportovat…", "description": "Button in the 'Trusted sites' pane" }, "whitelistExportFilename": { @@ -976,7 +976,7 @@ "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "Webová stránka...", + "message": "Webová stránka…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { @@ -1056,7 +1056,7 @@ "description": "Shown in the About pane" }, "aboutBackupDataButton": { - "message": "Zálohovat do souboru...", + "message": "Zálohovat do souboru…", "description": "Text for button to create a backup of all settings" }, "aboutBackupFilename": { @@ -1064,11 +1064,11 @@ "description": "English: my-ublock-backup_{{datetime}}.txt" }, "aboutRestoreDataButton": { - "message": "Obnovit ze souboru...", + "message": "Obnovit ze souboru…", "description": "English: Restore from file..." }, "aboutResetDataButton": { - "message": "Obnovit výchozí nastavení...", + "message": "Obnovit výchozí nastavení…", "description": "English: Reset to default settings..." }, "aboutRestoreDataConfirm": { @@ -1136,7 +1136,7 @@ "description": "Used in the strict-blocking page" }, "docblockedPrompt2": { - "message": "Kvůli následujícímu filtru:", + "message": "Toto se stalo kvůli následujícímu filtru:", "description": "Used in the strict-blocking page" }, "docblockedNoParamsPrompt": { @@ -1208,7 +1208,7 @@ "description": "tooltip" }, "cloudNoData": { - "message": "...\n...", + "message": "…\n…", "description": "" }, "cloudDeviceNamePrompt": { @@ -1236,11 +1236,11 @@ "description": "" }, "contextMenuBlockElementInFrame": { - "message": "Zablokovat prvek v rámci...", + "message": "Zablokovat prvek v rámci…", "description": "An entry in the browser's contextual menu" }, "contextMenuSubscribeToList": { - "message": "Přihlásit se k odběru seznamu filtrů...", + "message": "Přihlásit se k odběru seznamu filtrů…", "description": "An entry in the browser's contextual menu" }, "contextMenuTemporarilyAllowLargeMediaElements": { @@ -1248,7 +1248,7 @@ "description": "A context menu entry, present when large media elements have been blocked on the current site" }, "contextMenuViewSource": { - "message": "Zobrazit zdrojový kód...", + "message": "Zobrazit zdrojový kód…", "description": "A context menu entry, to view the source code of the target resource" }, "shortcutCapturePlaceholder": { diff --git a/src/_locales/cy/messages.json b/src/_locales/cy/messages.json index f4dc7be274e80..e97301e96d6a7 100644 --- a/src/_locales/cy/messages.json +++ b/src/_locales/cy/messages.json @@ -60,7 +60,7 @@ "description": "appears as tab name in dashboard" }, "assetViewerPageName": { - "message": "uBlock₀ — Asset viewer", + "message": "uBlock₀ — Gweld ased", "description": "Title for the asset viewer page" }, "advancedSettingsPageName": { @@ -80,7 +80,7 @@ "description": "Message to be read by screen readers" }, "popupBlockedRequestPrompt": { - "message": "requests blocked", + "message": "ceisiadau wedi'u bloc", "description": "English: requests blocked" }, "popupBlockedOnThisPagePrompt": { @@ -132,27 +132,27 @@ "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipNoPopups": { - "message": "Toggle the blocking of all popups for this site", + "message": "Troci blocio pob pob-wybrennau ar gyfer y safle hwn", "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoPopups1": { - "message": "Click to block all popups on this site", + "message": "Cliciwch i rwystro pob pob-wybren ar y safle hwn", "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoPopups2": { - "message": "Click to no longer block all popups on this site", + "message": "Cliciwch i beidio â blocio pob pob-wybren ar y safle hwn mwyach", "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoLargeMedia": { - "message": "Toggle the blocking of large media elements for this site", + "message": "Troci blocio elfennau cyfryngau mawr ar gyfer y safle hwn", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoLargeMedia1": { - "message": "Click to block large media elements on this site", + "message": "Cliciwch i rwystro elfennau cyfryngau mawr ar y safle hwn", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoLargeMedia2": { - "message": "Click to no longer block large media elements on this site", + "message": "Cliciwch i beidio â blocio elfennau cyfryngau mawr ar y safle hwn mwyach", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoCosmeticFiltering": { @@ -168,7 +168,7 @@ "description": "Tooltip for the no-cosmetic-filtering per-site switch" }, "popupTipNoRemoteFonts": { - "message": "Toggle the blocking of remote fonts for this site", + "message": "Troci blocio ffontiau o bell ar gyfer y safle hwn", "description": "Tooltip for the no-remote-fonts per-site switch" }, "popupTipNoRemoteFonts1": { @@ -216,19 +216,19 @@ "description": "Label to be used to hide popup panel sections" }, "popupTipGlobalRules": { - "message": "Global rules: this column is for rules which apply to all sites.", + "message": "Rheolau byd-eang: mae'r golofn hon ar gyfer rheolau sy'n berthnasol i bob safle.", "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Local rules: this column is for rules which apply to the current site only.", + "message": "Rheolau lleol: mae'r golofn hon ar gyfer rheolau sy'n berthnasol i'r safle presennol yn unig.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { - "message": "Click to make your changes permanent.", + "message": "Cliciwch i wneud eich newidiadau'n barhaol.", "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." }, "popupTipRevertRules": { - "message": "Click to revert your changes.", + "message": "Cliciwch i ddychwelyd eich newidiadau.", "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." }, "popupAnyRulePrompt": { @@ -248,23 +248,23 @@ "description": "" }, "popupInlineScriptRulePrompt": { - "message": "inline scripts", + "message": "sgriptiau mewnol", "description": "" }, "popup1pScriptRulePrompt": { - "message": "1st-party scripts", + "message": "sgriptiau parti 1af", "description": "" }, "popup3pScriptRulePrompt": { - "message": "3rd-party scripts", + "message": "sgriptiau trydydd parti", "description": "" }, "popup3pFrameRulePrompt": { - "message": "3rd-party frames", + "message": "fframiau trydydd parti", "description": "" }, "popupHitDomainCountPrompt": { - "message": "domains connected", + "message": "parthau cysylltiedig", "description": "appears in popup" }, "popupHitDomainCount": { @@ -300,7 +300,7 @@ "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" }, "pickerNetFilters": { - "message": "Network filters", + "message": "Hidlau rhwydwaith", "description": "English: header for a type of filter in the element picker dialog" }, "pickerCosmeticFilters": { @@ -308,7 +308,7 @@ "description": "English: Cosmetic filters" }, "pickerCosmeticFiltersHint": { - "message": "Click, Ctrl-click", + "message": "Cliciwch, Ctrl-clic", "description": "English: Click, Ctrl-click" }, "pickerContextMenuEntry": { @@ -316,23 +316,23 @@ "description": "An entry in the browser's contextual menu" }, "settingsCollapseBlockedPrompt": { - "message": "Hide placeholders of blocked elements", + "message": "Cuddio daliadau lle elfennau bloc", "description": "English: Hide placeholders of blocked elements" }, "settingsIconBadgePrompt": { - "message": "Show the number of blocked requests on the icon", + "message": "Dangos nifer y ceisiadau bloc ar yr eicon", "description": "English: Show the number of blocked requests on the icon" }, "settingsTooltipsPrompt": { - "message": "Disable tooltips", + "message": "Analluoga awgrymiadau offer", "description": "A checkbox in the Settings pane" }, "settingsContextMenuPrompt": { - "message": "Make use of context menu where appropriate", + "message": "Defnyddio'r ddewislen cyd-destun lle bo'n briodol", "description": "English: Make use of context menu where appropriate" }, "settingsColorBlindPrompt": { - "message": "Color-blind friendly", + "message": "Cyfeillgar i ddallwyr lliw", "description": "English: Color-blind friendly" }, "settingsAppearance": { @@ -344,11 +344,11 @@ "description": "Label for checkbox to enable a custom dark theme" }, "settingsThemeAccent0Label": { - "message": "Custom accent color", + "message": "Lliw acen personol", "description": "Label for checkbox to pick an accent color" }, "settingsCloudStorageEnabledPrompt": { - "message": "Enable cloud storage support", + "message": "Galluogi cefnogaeth storio cwmwl", "description": "" }, "settingsAdvancedUserPrompt": { @@ -356,11 +356,11 @@ "description": "Checkbox to let user access advanced, technical features" }, "settingsPrefetchingDisabledPrompt": { - "message": "Disable pre-fetching (to prevent any connection for blocked network requests)", + "message": "Analluogi rhag-llwytho (i atal unrhyw gysylltiad ar gyfer ceisiadau rhwydwaith bloc)", "description": "English: " }, "settingsHyperlinkAuditingDisabledPrompt": { - "message": "Disable hyperlink auditing", + "message": "Analluogi archwilio hypergysylltiad", "description": "English: " }, "settingsWebRTCIPAddressHiddenPrompt": { @@ -368,11 +368,11 @@ "description": "English: " }, "settingPerSiteSwitchGroup": { - "message": "Default behavior", + "message": "Ymddygiad diofyn", "description": "" }, "settingPerSiteSwitchGroupSynopsis": { - "message": "These default behaviors can be overridden on a per-site basis", + "message": "Gellir gor-reoli'r ymddygiadau diofyn hyn fesul safle", "description": "" }, "settingsNoCosmeticFilteringPrompt": { @@ -380,7 +380,7 @@ "description": "" }, "settingsNoLargeMediaPrompt": { - "message": "Block media elements larger than {{input}} KB", + "message": "Blocio elfennau cyfryngau sy'n fwy na {{input}} KB", "description": "" }, "settingsNoRemoteFontsPrompt": { @@ -392,11 +392,11 @@ "description": "The default state for the per-site no-scripting switch" }, "settingsNoCSPReportsPrompt": { - "message": "Block CSP reports", + "message": "Blocio adroddiadau CSP", "description": "background information: https://github.com/gorhill/uBlock/issues/3150" }, "settingsUncloakCnamePrompt": { - "message": "Uncloak canonical names", + "message": "Datguddio enwau canonaidd", "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" }, "settingsAdvanced": { @@ -404,7 +404,7 @@ "description": "Section for controlling advanced-user settings" }, "settingsAdvancedSynopsis": { - "message": "Features suitable only for technical users", + "message": "Nodweddion sy'n addas ar gyfer defnyddwyr technegol yn unig", "description": "Description of section controlling advanced-user settings" }, "settingsAdvancedUserSettings": { @@ -412,15 +412,15 @@ "description": "For the tooltip of a link which gives access to advanced settings" }, "settingsLastRestorePrompt": { - "message": "Last restore:", + "message": "Adferiad diwethaf:", "description": "English: Last restore:" }, "settingsLastBackupPrompt": { - "message": "Last backup:", + "message": "Copiau wrth gefn diwethaf:", "description": "English: Last backup:" }, "3pListsOfBlockedHostsPrompt": { - "message": "{{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:", + "message": "{{netFilterCount}} hidl rhwydwaith + {{cosmeticFilterCount}} hidl cosmetig o:", "description": "Appears at the top of the _3rd-party filters_ pane" }, "3pListsOfBlockedHostsPerListStats": { @@ -428,7 +428,7 @@ "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "3pAutoUpdatePrompt1": { - "message": "Auto-update filter lists", + "message": "Diweddaru rhestrau hidl yn awtomatig", "description": "A checkbox in the _3rd-party filters_ pane" }, "3pUpdateNow": { @@ -436,15 +436,15 @@ "description": "A button in the in the _3rd-party filters_ pane" }, "3pPurgeAll": { - "message": "Purge all caches", + "message": "Clirio pob storfa", "description": "A button in the in the _3rd-party filters_ pane" }, "3pParseAllABPHideFiltersPrompt1": { - "message": "Parse and enforce cosmetic filters", + "message": "Dadansoddi a gorfodi hidlau cosmetig", "description": "English: Parse and enforce Adblock+ element hiding filters." }, "3pParseAllABPHideFiltersInfo": { - "message": "Cosmetic filters serve to hide elements in a web page which are deemed to be a visual nuisance, and which can't be blocked by the network request-based filtering engines.", + "message": "Mae hidlau cosmetig yn gwasanaethu i guddio elfennau mewn tudalen we sy'n cael eu hystyried yn niwsans gweledol, ac na ellir eu blocio gan beiriannau hidlo sy'n seiliedig ar geisiadau rhwydwaith.", "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." }, "3pIgnoreGenericCosmeticFilters": { @@ -456,7 +456,7 @@ "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." }, "3pSuspendUntilListsAreLoaded": { - "message": "Suspend network activity until all filter lists are loaded", + "message": "Atal gweithgaredd rhwydwaith nes bod pob rhestr hidl wedi'u llwytho", "description": "A checkbox in the 'Filter lists' pane" }, "3pListsOfBlockedHostsHeader": { @@ -484,7 +484,7 @@ "description": "Filter lists section name" }, "3pGroupSocial": { - "message": "Social widgets", + "message": "Teclynnau cymdeithasol", "description": "Filter lists section name" }, "3pGroupCookies": { @@ -512,7 +512,7 @@ "description": "The label for the checkbox used to import external filter lists" }, "3pExternalListsHint": { - "message": "One URL per line. Invalid URLs will be silently ignored.", + "message": "Un URL fesul llinell. Caiff URLs annilys eu hanwybyddu'n dawel.", "description": "Short information about how to use the textarea to import external filter lists by URL" }, "3pExternalListObsolete": { @@ -524,7 +524,7 @@ "description": "used as a tooltip for eye icon beside a list" }, "3pLastUpdate": { - "message": "Last update: {{ago}}.\nClick to force an update.", + "message": "Diweddariad diwethaf: {{ago}}.\nCliciwch i orfodi diweddariad.", "description": "used as a tooltip for the clock icon beside a list" }, "3pUpdating": { @@ -532,11 +532,11 @@ "description": "used as a tooltip for the spinner icon beside a list" }, "3pNetworkError": { - "message": "A network error prevented the resource from being updated.", + "message": "Ataliodd gwall rhwydwaith yr adnodd rhag cael ei ddiweddaru.", "description": "used as a tooltip for error icon beside a list" }, "1pTrustWarning": { - "message": "Do not add filters from untrusted sources.", + "message": "Peidiwch â ychwanegu hidlau o ffynonellau anniogel.", "description": "Warning against copy-pasting filters from random sources" }, "1pEnableMyFiltersLabel": { @@ -544,7 +544,7 @@ "description": "Label for the checkbox use to enable/disable 'My filters' list" }, "1pTrustMyFiltersLabel": { - "message": "Allow custom filters requiring trust", + "message": "Caniatáu hidlau arferol sy'n gofyn am ymddiriedaeth", "description": "Label for the checkbox use to trust the content of 'My filters' list" }, "1pImport": { @@ -608,7 +608,7 @@ "description": "English: List of your dynamic filtering rules." }, "rulesFormatHint": { - "message": "Rule syntax: source destination type action (full documentation).", + "message": "Cystrawen rheol: ffynhonnell cyrchfan math gweithred (dogfennaeth lawn).", "description": "English: dynamic rule syntax and full documentation." }, "rulesSort": { @@ -628,7 +628,7 @@ "description": "English: a sort option for list of rules." }, "whitelistPrompt": { - "message": "The trusted site directives dictate on which web pages uBlock Origin should be disabled. One entry per line.", + "message": "Mae cyfarwyddiadau safle dibynadwy yn pennu ar ba dudalennau gwe y dylid analluogi uBlock Origin. Un cofnod fesul llinell.", "description": "A concise description of the 'Trusted sites' pane." }, "whitelistImport": { @@ -668,7 +668,7 @@ "description": "Appears in the logger's tab selector" }, "logBehindTheScene": { - "message": "Tabless", + "message": "Di-dab", "description": "Pretty name for behind-the-scene network requests" }, "loggerCurrentTab": { @@ -676,19 +676,19 @@ "description": "Appears in the logger's tab selector" }, "loggerReloadTip": { - "message": "Reload the tab content", + "message": "Ail-lwytho cynnwys y tab", "description": "Tooltip for the reload button in the logger page" }, "loggerDomInspectorTip": { - "message": "Toggle the DOM inspector", + "message": "Troci archwiliwr DOM", "description": "Tooltip for the DOM inspector button in the logger page" }, "loggerPopupPanelTip": { - "message": "Toggle the popup panel", + "message": "Troci panel naid", "description": "Tooltip for the popup panel button in the logger page" }, "loggerInfoTip": { - "message": "uBlock Origin wiki: The logger", + "message": "Wici uBlock Origin: Y logiwr", "description": "Tooltip for the top-right info label in the logger page" }, "loggerClearTip": { @@ -736,7 +736,7 @@ "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltin1p": { - "message": "1st-party", + "message": "parti 1af", "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltin3p": { @@ -752,7 +752,7 @@ "description": "Label to identify a filter field" }, "loggerEntryDetailsFilterList": { - "message": "Filter list", + "message": "Rhestr hidl", "description": "Label to identify a filter list field" }, "loggerEntryDetailsRule": { @@ -764,7 +764,7 @@ "description": "Label to identify a context field (typically a hostname)" }, "loggerEntryDetailsRootContext": { - "message": "Root context", + "message": "Cyd-destun gwraidd", "description": "Label to identify a root context field (typically a hostname)" }, "loggerEntryDetailsPartyness": { @@ -796,7 +796,7 @@ "description": "Small header to identify the static filtering section" }, "loggerStaticFilteringSentence": { - "message": "{{action}} network requests of {{type}} {{br}}which URL address matches {{url}} {{br}}and which originates {{origin}},{{br}}{{importance}} there is a matching exception filter.", + "message": "{{action}} ceisiadau rhwydwaith o {{type}} {{br}}y mae ei gyfeiriad URL yn cyfateb i {{url}} {{br}}ac sy'n tarddu o {{origin}},{{br}}{{importance}} mae hidl eithriad sy'n cyfateb.", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartBlock": { @@ -832,31 +832,31 @@ "description": "Used in the static filtering wizard" }, "loggerStaticFilteringFinderSentence1": { - "message": "Static filter {{filter}} found in:", + "message": "Hidl sefydlog {{filter}} a geir yn:", "description": "Below this sentence, the filter list(s) in which the filter was found" }, "loggerStaticFilteringFinderSentence2": { - "message": "Static filter could not be found in any of the currently enabled filter lists", + "message": "Ni ellid dod o hyd i hidl sefydlog yn unrhyw un o'r rhestrau hidl sydd wedi'u galluogi ar hyn o bryd", "description": "Message to show when a filter cannot be found in any filter lists" }, "loggerSettingDiscardPrompt": { - "message": "Logger entries which do not fulfill all three conditions below will be automatically discarded:", + "message": "Bydd cofnodion logiwr nad ydynt yn cyflawni'r tair amod isod yn cael eu taflu'n awtomatig:", "description": "Logger setting: A sentence to describe the purpose of the settings below" }, "loggerSettingPerEntryMaxAge": { - "message": "Preserve entries from the last {{input}} minutes", + "message": "Cadw cofnodion o'r {{input}} munud diwethaf", "description": "A logger setting" }, "loggerSettingPerTabMaxLoads": { - "message": "Preserve at most {{input}} page loads per tab", + "message": "Cadw uchafswm o {{input}} llwythiadau tudalen fesul tab", "description": "A logger setting" }, "loggerSettingPerTabMaxEntries": { - "message": "Preserve at most {{input}} entries per tab", + "message": "Cadw uchafswm o {{input}} cofnodion fesul tab", "description": "A logger setting" }, "loggerSettingPerEntryLineCount": { - "message": "Use {{input}} lines per entry in vertically expanded mode", + "message": "Defnyddio {{input}} llinell fesul cofnod yn y modd lledaenu fertigol", "description": "A logger setting" }, "loggerSettingHideColumnsPrompt": { @@ -876,7 +876,7 @@ "description": "A label for the context column" }, "loggerSettingHideColumnPartyness": { - "message": "{{input}} Partyness", + "message": "{{input}} Parti-", "description": "A label for the partyness column" }, "loggerExportFormatList": { @@ -912,7 +912,7 @@ "description": "Header of 'Documentation' section in Support pane" }, "supportS1P1": { - "message": "Read the documentation at uBlock/wiki to learn about all of uBlock Origin's features.", + "message": "Darllenwch y ddogfennaeth yn uBlock/wiki i ddysgu am holl nodweddion uBlock Origin.", "description": "First paragraph of 'Documentation' section in Support pane" }, "supportS2H": { @@ -920,23 +920,23 @@ "description": "Header of 'Questions and support' section in Support pane" }, "supportS2P1": { - "message": "Answers to questions and other kinds of help support is provided on the subreddit /r/uBlockOrigin.", + "message": "Darperir atebion i gwestiynau a chymorth arall ar yr is-reddit /r/uBlockOrigin.", "description": "First paragraph of 'Questions and support' section in Support pane" }, "supportS3H": { - "message": "Filter issues/website is broken", + "message": "Problemau hidlo / gwefan wedi torri", "description": "Header of 'Filter issues' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "Adroddwch am broblemau hidlo gyda gwefannau penodol i uBlockOrigin/uAssets olrheiniwr materion. Mae angen cyfrif GitHub.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS3P2": { - "message": "Important: Avoid using other similarly-purposed blockers along with uBlock Origin, as this may cause filter issues on specific websites.", + "message": "Pwysig: Osgowch ddefnyddio rhwystrwyr eraill o ddiben tebyg ochr yn ochr ag uBlock Origin, gan y gallai hyn achosi problemau hidlo ar wefannau penodol.", "description": "Second paragraph of 'Filter issues' section in Support pane" }, "supportS3P3": { - "message": "Tips: Be sure your filter lists are up to date. The logger is the primary tool to diagnose filter-related issues.", + "message": "Awgrymiadau: Gwnewch yn siŵr bod eich rhestrau hidl yn gyfoes. Y logiwr yw'r prif offeryn i ddiagnosio problemau sy'n ymwneud â hidlo.", "description": "Third paragraph of 'Filter issues' section in Support pane" }, "supportS4H": { @@ -944,7 +944,7 @@ "description": "Header of 'Bug report' section in Support pane" }, "supportS4P1": { - "message": "Report issues with uBlock Origin itself to the uBlockOrigin/uBlock-issue issue tracker. Requires a GitHub account.", + "message": "Adroddwch am broblemau gydag uBlock Origin ei hun i uBlockOrigin/uBlock-issue olrheiniwr materion. Mae angen cyfrif GitHub.", "description": "First paragraph of 'Bug report' section in Support pane" }, "supportS5H": { @@ -952,7 +952,7 @@ "description": "Header of 'Troubleshooting Information' section in Support pane" }, "supportS5P1": { - "message": "Below is technical information that might be useful when volunteers are trying to help you solve a problem.", + "message": "Isod mae gwybodaeth dechnegol a allai fod yn ddefnyddiol pan fydd gwirfoddolwyr yn ceisio'ch helpu i ddatrys problem.", "description": "First paragraph of 'Troubleshooting Information' section in Support pane" }, "supportS6H": { @@ -960,15 +960,15 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "Er mwyn osgoi baich ar wirfoddolwyr gydag adroddiadau dyblyg, gwiriwch nad yw'r mater eisoes wedi'i adrodd. Nodyn: bydd clicio'r botwm yn achosi i darddiad y dudalen gael ei anfon i GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { - "message": "Filter lists are updated daily. Be sure your issue has not already been addressed in the most recent filter lists.", + "message": "Mae rhestrau hidl yn cael eu diweddaru'n ddyddiol. Gwnewch yn siŵr nad yw'ch mater eisoes wedi'i ddatrys yn y rhestrau hidl diweddaraf.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S2": { - "message": "Verify that the issue still exists after reloading the problematic web page.", + "message": "Gwiriwch fod y mater yn dal i fodoli ar ôl ail-lwytho'r dudalen we broblemus.", "description": "A paragraph in the filter issue reporter section" }, "supportS6URL": { @@ -980,7 +980,7 @@ "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- Dewiswch gofnod --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { @@ -988,7 +988,7 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "Mae gorgysylltiadau neu niwsansau eraill", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { @@ -1000,15 +1000,15 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBlock Origin is enabled", + "message": "Yn camweithio pan fydd uBlock Origin wedi'i alluogi", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "Yn agor tabiau neu ffenestri diangen", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "Yn arwain at feddalwedd faleisus, gwe-rwydo", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { @@ -1048,11 +1048,11 @@ "description": "Shown in the About pane" }, "aboutCDNs": { - "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "message": "Mae rhestrau hidl uBO eu hunain yn cael eu cynnal am ddim ar y CDNs canlynol:", "description": "Shown in the About pane" }, "aboutCDNsInfo": { - "message": "A randomly picked CDN is used when a filter list needs to be updated.", + "message": "Defnyddir CDN a ddewiswyd ar hap pan fydd angen diweddaru rhestr hidl.", "description": "Shown in the About pane" }, "aboutBackupDataButton": { @@ -1072,15 +1072,15 @@ "description": "English: Reset to default settings..." }, "aboutRestoreDataConfirm": { - "message": "All your settings will be overwritten using data backed up on {{time}}, and uBlock₀ will restart.\n\nOverwrite all existing settings using backed up data?", + "message": "Bydd eich holl osodiadau'n cael eu trosysgrifo gan ddefnyddio data a gopïwyd wrth gefn ar {{time}}, a bydd uBlock₀ yn ailgychwyn.\n\nA ydych am drosysgrifo pob gosodiad presennol gan ddefnyddio data wrth gefn?", "description": "Message asking user to confirm restore" }, "aboutRestoreDataError": { - "message": "The data could not be read or is invalid", + "message": "Ni ellid darllen y data neu mae'n annilys", "description": "Message to display when an error occurred during restore" }, "aboutResetDataConfirm": { - "message": "All your settings will be removed, and uBlock₀ will restart.\n\nReset uBlock₀ to factory settings?", + "message": "Caiff eich holl osodiadau eu tynnu, a bydd uBlock₀ yn ailgychwyn.\n\nAilgychwyn uBlock₀ i osodiadau ffatri?", "description": "Message asking user to confirm reset" }, "errorCantConnectTo": { @@ -1144,7 +1144,7 @@ "description": "label to be used for the parameter-less URL: https://cloud.githubusercontent.com/assets/585534/9832014/bfb1b8f0-593b-11e5-8a27-fba472a5529a.png" }, "docblockedFoundIn": { - "message": "The filter has been found in:", + "message": "Mae'r hidl wedi'i ddarganfod yn:", "description": "English: List of filter list names follows" }, "docblockedBack": { @@ -1160,7 +1160,7 @@ "description": "Label for checkbox in document-blocked page" }, "docblockedProceed": { - "message": "Disable strict blocking for {{hostname}}", + "message": "Analluogi blocio llym ar gyfer {{hostname}}", "description": "English: Disable strict blocking for {{hostname}} ..." }, "docblockedDisableTemporary": { @@ -1176,7 +1176,7 @@ "description": "Button text to navigate to the blocked page" }, "docblockedRedirectPrompt": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "Mae'r dudalen rwystredig am ailgyfeirio i safle arall. Os dewiswch fwrw ymlaen, byddwch yn llywio'n uniongyrchol i: {{url}}", "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { @@ -1192,19 +1192,19 @@ "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { - "message": "Disreputable", + "message": "Amheus", "description": "An actual reason why a page was blocked" }, "cloudPush": { - "message": "Export to cloud storage", + "message": "Allforio i storfa cwmwl", "description": "tooltip" }, "cloudPull": { - "message": "Import from cloud storage", + "message": "Mewnforio o storfa cwmwl", "description": "tooltip" }, "cloudPullAndMerge": { - "message": "Import from cloud storage and merge with current settings", + "message": "Mewnforio o storfa cwmwl a chyfuno â gosodiadau cyfredol", "description": "tooltip" }, "cloudNoData": { @@ -1216,7 +1216,7 @@ "description": "used as a prompt for the user to provide a custom device name" }, "advancedSettingsWarning": { - "message": "Warning! Change these advanced settings at your own risk.", + "message": "Rhybudd! Newidiwch y gosodiadau uwch hyn ar eich menter eich hun.", "description": "A warning to users at the top of 'Advanced settings' page" }, "genericSubmit": { @@ -1236,15 +1236,15 @@ "description": "" }, "contextMenuBlockElementInFrame": { - "message": "Block element in frame…", + "message": "Blocio elfen mewn ffrâm…", "description": "An entry in the browser's contextual menu" }, "contextMenuSubscribeToList": { - "message": "Subscribe to filter list…", + "message": "Tanysgrifio i restr hidl…", "description": "An entry in the browser's contextual menu" }, "contextMenuTemporarilyAllowLargeMediaElements": { - "message": "Temporarily allow large media elements", + "message": "Caniatáu elfennau cyfryngau mawr dros dro", "description": "A context menu entry, present when large media elements have been blocked on the current site" }, "contextMenuViewSource": { @@ -1252,11 +1252,11 @@ "description": "A context menu entry, to view the source code of the target resource" }, "shortcutCapturePlaceholder": { - "message": "Type a shortcut", + "message": "Teipiwch lwybr byr", "description": "Placeholder string for input field used to capture a keyboard shortcut" }, "genericMergeViewScrollLock": { - "message": "Toggle locked scrolling", + "message": "Troci sgrolio cloi", "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" }, "genericCopyToClipboard": { @@ -1276,7 +1276,7 @@ "description": "Label for keyboard shortcut used to toggle no-scripting switch" }, "relaxBlockingMode": { - "message": "Relax blocking mode", + "message": "Lleddfu modd blocio", "description": "Label for keyboard shortcut used to relax blocking mode" }, "storageUsed": { @@ -1304,7 +1304,7 @@ "description": "Summary of number of errors as reported by the linter " }, "unprocessedRequestTooltip": { - "message": "Could not filter properly at browser launch. Reload the page to ensure proper filtering.", + "message": "Methwyd hidlo'n iawn wrth lansio'r porwr. Ail-lwythwch y dudalen i sicrhau hidlo priodol.", "description": "A warning which will appear in the popup panel if needed" }, "dummy": { diff --git a/src/_locales/da/messages.json b/src/_locales/da/messages.json index 11ea7bd5271d4..d885364d02c48 100644 --- a/src/_locales/da/messages.json +++ b/src/_locales/da/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Lokale regler: denne søjle viser de regler der gælder kun på denne side.\nLokale regler overskriver globale regler.", + "message": "Lokale regler: Søjlen viser de regler, som alene gælder på det aktuelle websted.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { diff --git a/src/_locales/de/messages.json b/src/_locales/de/messages.json index 01a1dc11f2b7a..c72e34875f9bf 100644 --- a/src/_locales/de/messages.json +++ b/src/_locales/de/messages.json @@ -52,11 +52,11 @@ "description": "Title for the logger window" }, "aboutPageName": { - "message": "Über", + "message": "Informationen", "description": "appears as tab name in dashboard" }, "supportPageName": { - "message": "Unterstützung", + "message": "Support", "description": "appears as tab name in dashboard" }, "assetViewerPageName": { diff --git a/src/_locales/el/messages.json b/src/_locales/el/messages.json index b4623718730b4..b133d93abd288 100644 --- a/src/_locales/el/messages.json +++ b/src/_locales/el/messages.json @@ -12,7 +12,7 @@ "description": "English: uBlock₀ — Dashboard" }, "dashboardUnsavedWarning": { - "message": "Προειδοποίηση! Έχετε μη αποθηκευμένες αλλαγές", + "message": "Προειδοποίηση: έχετε μη αποθηκευμένες αλλαγές!", "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { @@ -68,15 +68,15 @@ "description": "Title for the advanced settings page" }, "popupPowerSwitchInfo": { - "message": "Κλικ: απενεργοποίηση/ενεργοποίηση του uBlock₀ για αυτόν τον ιστότοπο.\n\nCtrl+κλικ: απενεργοποίηση του uBlock₀ μόνο για αυτήν την σελίδα.", + "message": "Κλικ: απενεργοποίηση/ενεργοποίηση του uBlock₀ για αυτόν τον ιστότοπο.\n\nCtrl+κλικ: απενεργοποίηση του uBlock₀ μόνο σε αυτήν τη σελίδα.", "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." }, "popupPowerSwitchInfo1": { - "message": "Κάντε κλικ για απενεργοποίηση του uBlock₀ για αυτήν την ιστοσελίδα.\n\nCtrl+κλικ για απενεργοποίηση του uBlock₀ μόνο σε αυτήν τη σελίδα.", + "message": "Κάντε κλικ για απενεργοποίηση του uBlock₀ για αυτόν τον ιστότοπο.\n\nCtrl+κλικ για απενεργοποίηση του uBlock₀ μόνο σε αυτήν τη σελίδα.", "description": "Message to be read by screen readers" }, "popupPowerSwitchInfo2": { - "message": "Κάντε κλικ για ενεργοποίηση του uBlock₀ για αυτή την ιστοσελίδα.", + "message": "Κάντε κλικ για ενεργοποίηση του uBlock₀ για αυτόν τον ιστότοπο.", "description": "Message to be read by screen readers" }, "popupBlockedRequestPrompt": { @@ -100,11 +100,11 @@ "description": "English: or" }, "popupBlockedOnThisPage_v2": { - "message": "Αποκλεισμένα σε αυτή τη σελίδα", + "message": "Αποκλεισμένα σε αυτήν τη σελίδα", "description": "For the new mobile-friendly popup design" }, "popupBlockedSinceInstall_v2": { - "message": "Φραγμένο από εγκατάσταση", + "message": "Αποκλεισμένο από εγκατάσταση", "description": "For the new mobile-friendly popup design" }, "popupDomainsConnected_v2": { @@ -112,7 +112,7 @@ "description": "For the new mobile-friendly popup design" }, "popupTipDashboard": { - "message": "Κάντε κλικ για να ανοίξετε τον πίνακα εργαλείων", + "message": "Ανοίξτε τον πίνακα ελέγχου", "description": "English: Click to open the dashboard" }, "popupTipZapper": { @@ -128,7 +128,7 @@ "description": "Tooltip used for the logger icon in the panel" }, "popupTipReport": { - "message": "Αναφέρετε ένα πρόβλημα σε αυτόν τον ιστότοπο", + "message": "Αναφέρετε ένα σφάλμα σε αυτόν τον ιστότοπο", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipNoPopups": { @@ -356,7 +356,7 @@ "description": "Checkbox to let user access advanced, technical features" }, "settingsPrefetchingDisabledPrompt": { - "message": "Απενεργοποίηση προ-φόρτωσης (για να αποτραπεί κάθε σύνδεση σε αποκλεισμένες αιτήσεις δικτύου)", + "message": "Απενεργοποίηση πρόωρης φόρτωσης (για να αποτραπεί κάθε σύνδεση σε μπλοκαρισμένες αιτήσεις δικτύου)", "description": "English: " }, "settingsHyperlinkAuditingDisabledPrompt": { @@ -404,7 +404,7 @@ "description": "Section for controlling advanced-user settings" }, "settingsAdvancedSynopsis": { - "message": "Χαρακτηριστικά κατάλληλα μόνο για τεχνικούς χρήστες.", + "message": "Χαρακτηριστικά κατάλληλα μόνο για τεχνικούς χρήστες", "description": "Description of section controlling advanced-user settings" }, "settingsAdvancedUserSettings": { @@ -512,11 +512,11 @@ "description": "The label for the checkbox used to import external filter lists" }, "3pExternalListsHint": { - "message": "Ένα URL ανά γραμμή. Γραμμές με το πρόθεμα ‘!’ θα παραβλέπονται. Άκυρα URL θα παρακάμπτονται σιωπηλά.", + "message": "Ένα URL ανά γραμμή. Άκυρα URL θα παρακάμπτονται σιωπηλά.", "description": "Short information about how to use the textarea to import external filter lists by URL" }, "3pExternalListObsolete": { - "message": "απαρχαιωμένη.", + "message": "Μη ενημερωμένη.", "description": "used as a tooltip for the out-of-date icon beside a list" }, "3pViewContent": { @@ -960,7 +960,7 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "Για να αποφύγετε την επιβάρυνση των εθελοντών με διπλές αναφορές, βεβαιωθείτε ότι το ζήτημα δεν έχει ήδη αναφερθεί.", + "message": "Για να μην επιβαρυνθούν οι εθελοντών με διπλές αναφορές, βεβαιωθείτε ότι το ζήτημα δεν έχει ήδη αναφερθεί.Σημείωση: Με το πάτημα του κουμπιού, θα σταλεί η σελίδα προέλευσης στο GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { diff --git a/src/_locales/en_GB/messages.json b/src/_locales/en_GB/messages.json index a211abc6b50e9..bbe976d66d4cf 100644 --- a/src/_locales/en_GB/messages.json +++ b/src/_locales/en_GB/messages.json @@ -444,7 +444,7 @@ "description": "English: Parse and enforce Adblock+ element hiding filters." }, "3pParseAllABPHideFiltersInfo": { - "message": "Cosmetic filters serve to hide elements in a web page which are deemed to be a visual nuisance, and which cannot be blocked by the network request-based filtering engines.", + "message": "Cosmetic filters serve to hide elements in a webpage which are deemed to be a visual nuisance, and which cannot be blocked by the network request-based filtering engines.", "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." }, "3pIgnoreGenericCosmeticFilters": { @@ -452,7 +452,7 @@ "description": "This will cause uBO to ignore all generic cosmetic filters." }, "3pIgnoreGenericCosmeticFiltersInfo": { - "message": "Generic cosmetic filters are those cosmetic filters which are meant to apply on all web sites. Enabling this option will eliminate the memory and CPU overhead added to web pages as a result of handling generic cosmetic filters.\n\nIt is recommended to enable this option on less powerful devices.", + "message": "Generic cosmetic filters are those cosmetic filters which are meant to apply on all websites. Enabling this option will eliminate the memory and CPU overhead added to webpages as a result of handling generic cosmetic filters.\n\nIt is recommended to enable this option on less powerful devices.", "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." }, "3pSuspendUntilListsAreLoaded": { @@ -628,7 +628,7 @@ "description": "English: a sort option for list of rules." }, "whitelistPrompt": { - "message": "The trusted site directives dictate on which web pages uBlock Origin should be disabled. One entry per line.", + "message": "The trusted site directives dictate on which webpages uBlock Origin should be disabled. One entry per line.", "description": "A concise description of the 'Trusted sites' pane." }, "whitelistImport": { @@ -900,11 +900,11 @@ "description": "Text for button which open an external web page in Support pane" }, "supportReportSpecificButton": { - "message": "Create new report", + "message": "Create new report on GitHub", "description": "Text for button which open an external web page in Support pane" }, "supportFindSpecificButton": { - "message": "Find similar reports", + "message": "Find similar reports on GitHub", "description": "A clickable link in the filter issue reporter section" }, "supportS1H": { @@ -960,7 +960,7 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported.", + "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { @@ -972,11 +972,11 @@ "description": "A paragraph in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "Address of the webpage:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "The webpage…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { @@ -1012,7 +1012,7 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "Label the webpage as “NSFW” (“Not Safe For Work”)", "description": "A checkbox to use for NSFW sites" }, "aboutPrivacyPolicy": { @@ -1052,7 +1052,7 @@ "description": "Shown in the About pane" }, "aboutCDNsInfo": { - "message": "A randomly picked CDN is used when a filter list needs to be updated", + "message": "A randomly picked CDN is used when a filter list needs to be updated.", "description": "Shown in the About pane" }, "aboutBackupDataButton": { @@ -1136,7 +1136,7 @@ "description": "Used in the strict-blocking page" }, "docblockedPrompt2": { - "message": "Because of the following filter:", + "message": "This happened because of the following filter:", "description": "Used in the strict-blocking page" }, "docblockedNoParamsPrompt": { diff --git a/src/_locales/eo/messages.json b/src/_locales/eo/messages.json index 7e0f5538bf336..149a38fc69b62 100644 --- a/src/_locales/eo/messages.json +++ b/src/_locales/eo/messages.json @@ -68,7 +68,7 @@ "description": "Title for the advanced settings page" }, "popupPowerSwitchInfo": { - "message": "Klako: malŝalti/ŝalti uBlock₀ por ĉi tiu retejo.\n\nCtrl+klako: malŝalti uBlock₀ nur en ĉi tiu paĝo.", + "message": "Klako: malŝalti/ŝalti uBlock₀ por ĉi tiu retejo.\n\nStir+klako: malŝalti uBlock₀ nur en ĉi tiu paĝo.", "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." }, "popupPowerSwitchInfo1": { @@ -144,7 +144,7 @@ "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoLargeMedia": { - "message": "Baskuligi la blokadon de grandaj aŭdvideaj elementoj por ĉi tiu retejo", + "message": "Baskuligi la blokadon de grandaj aŭdvidaj elementoj en tiu ĉi retejo", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoLargeMedia1": { @@ -400,7 +400,7 @@ "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" }, "settingsAdvanced": { - "message": "Altnivelaĵoj", + "message": "Altnivelaj agordoj", "description": "Section for controlling advanced-user settings" }, "settingsAdvancedSynopsis": { @@ -428,7 +428,7 @@ "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "3pAutoUpdatePrompt1": { - "message": "Ĝisdatigi listojn de filtriloj aŭtomate.", + "message": "Ĝisdatigi listojn de filtriloj aŭtomate", "description": "A checkbox in the _3rd-party filters_ pane" }, "3pUpdateNow": { @@ -440,7 +440,7 @@ "description": "A button in the in the _3rd-party filters_ pane" }, "3pParseAllABPHideFiltersPrompt1": { - "message": "Analizi kaj eltrudi ornamajn filtrilojn.", + "message": "Analizi kaj eltrudi ornamajn filtrilojn", "description": "English: Parse and enforce Adblock+ element hiding filters." }, "3pParseAllABPHideFiltersInfo": { @@ -480,7 +480,7 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "Domajno kun fiprogramaro", + "message": "Protekto kontraŭ fiprogramaro, sekureco", "description": "Filter lists section name" }, "3pGroupSocial": { @@ -508,7 +508,7 @@ "description": "Filter lists section name" }, "3pImport": { - "message": "Importi...", + "message": "Importi…", "description": "The label for the checkbox used to import external filter lists" }, "3pExternalListsHint": { @@ -516,7 +516,7 @@ "description": "Short information about how to use the textarea to import external filter lists by URL" }, "3pExternalListObsolete": { - "message": "malaktuala", + "message": "Malaktuala.", "description": "used as a tooltip for the out-of-date icon beside a list" }, "3pViewContent": { @@ -524,11 +524,11 @@ "description": "used as a tooltip for eye icon beside a list" }, "3pLastUpdate": { - "message": "Lasta ĝisdatigo: {{ago}}", + "message": "Lasta ĝisdatigo: {{ago}}.\nKlaku por ĝisdatigi nun.", "description": "used as a tooltip for the clock icon beside a list" }, "3pUpdating": { - "message": "Ĝisdatigo...", + "message": "Ĝisdatigo…", "description": "used as a tooltip for the spinner icon beside a list" }, "3pNetworkError": { @@ -592,11 +592,11 @@ "description": "Will discard manually-edited content and exit manual-edit mode" }, "rulesImport": { - "message": "Importi el dosiero...", + "message": "Importi el dosiero…", "description": "" }, "rulesExport": { - "message": "Eksporti al dosiero", + "message": "Eksporti al dosiero…", "description": "Button in the 'My rules' pane" }, "rulesDefaultFileName": { @@ -848,15 +848,15 @@ "description": "A logger setting" }, "loggerSettingPerTabMaxLoads": { - "message": "Preserve at most {{input}} page loads per tab", + "message": "Teni maksimume {{input}} paĝo-ŝargojn en ĉiu langeto", "description": "A logger setting" }, "loggerSettingPerTabMaxEntries": { - "message": "Preserve at most {{input}} entries per tab", + "message": "Teni maksimume {{input}} elementojn en ĉiu langeto", "description": "A logger setting" }, "loggerSettingPerEntryLineCount": { - "message": "Use {{input}} lines per entry in vertically expanded mode", + "message": "Uzi {{input}} liniojn en elemento en vertikale vasta reĝimo", "description": "A logger setting" }, "loggerSettingHideColumnsPrompt": { @@ -920,7 +920,7 @@ "description": "Header of 'Questions and support' section in Support pane" }, "supportS2P1": { - "message": "Answers to questions and other kinds of help support is provided on the subreddit /r/uBlockOrigin.", + "message": "Respondojn al demandoj kaj alian helpon provizas la subreddit /r/uBlockOrigin.", "description": "First paragraph of 'Questions and support' section in Support pane" }, "supportS3H": { @@ -932,11 +932,11 @@ "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS3P2": { - "message": "Important: Avoid using other similarly-purposed blockers along with uBlock Origin, as this may cause filter issues on specific websites.", + "message": "Atentu: eviti la uzadon de aliaj, similaj reklamoblokiloj kun uBlock Origin, ĉar tio eblas kaŭzi filtradajn problemojn en apartaj retejoj.", "description": "Second paragraph of 'Filter issues' section in Support pane" }, "supportS3P3": { - "message": "Tips: Be sure your filter lists are up to date. The logger is the primary tool to diagnose filter-related issues.", + "message": "Konsiletoj: konfirmu vian filtradajn listojn estas aktuala. La protokolilo estas la ĉefa ilo por analizi problemojn kiuj rilatas al filtrado.", "description": "Third paragraph of 'Filter issues' section in Support pane" }, "supportS4H": { @@ -960,15 +960,15 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "Por eviti ŝarĝi volontulojn per duplikataj raportoj, bonvolu konfirmi ke la problemo ankoraŭ ne raportitas. Noto: klaki la butonon kaŭzas ke la HTTP-origino de la paĝo senditas al GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { - "message": "Filter lists are updated daily. Be sure your issue has not already been addressed in the most recent filter lists.", + "message": "Filtradoj listoj ĝisdatiĝas tage. Konfirmu ke via problemo ankoraŭ ne riparitas per la plej novaj filtradaj listoj.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S2": { - "message": "Verify that the issue still exists after reloading the problematic web page.", + "message": "Konfirmu ke la problemo ankoraŭ ekzistas reŝarginte la probleman retpaĝon.", "description": "A paragraph in the filter issue reporter section" }, "supportS6URL": { @@ -1000,7 +1000,7 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Misfunkcias, se uBlock Origin estas ŝaltita ", + "message": "Misfunkcias, se uBlock Origin estas ŝaltita", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { @@ -1008,7 +1008,7 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "Sekvas malbon-programoj, trompo-retejoj", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { @@ -1064,11 +1064,11 @@ "description": "English: my-ublock-backup_{{datetime}}.txt" }, "aboutRestoreDataButton": { - "message": "Restaŭri el dosiero...", + "message": "Restaŭri el dosiero…", "description": "English: Restore from file..." }, "aboutResetDataButton": { - "message": "Remeti normajn agordojn...", + "message": "Remeti normajn agordojn…", "description": "English: Reset to default settings..." }, "aboutRestoreDataConfirm": { @@ -1156,7 +1156,7 @@ "description": "English: Close this window" }, "docblockedDontWarn": { - "message": "Don't warn me again about this site", + "message": "Ne plu avertu min pri tiu ĉi retejo", "description": "Label for checkbox in document-blocked page" }, "docblockedProceed": { @@ -1176,23 +1176,23 @@ "description": "Button text to navigate to the blocked page" }, "docblockedRedirectPrompt": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "La blokita paĝo volas fordirekti al alia retejo. Se vi daŭras, vi navigos senpere al {{url}}", "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { - "message": "Reason:", + "message": "Kialo:", "description": "The label which prepend the actual reason why a page was blocked" }, "docblockedReasonMalicious": { - "message": "Malicious", + "message": "Malica", "description": "An actual reason why a page was blocked" }, "docblockedReasonTracker": { - "message": "Tracker", + "message": "Spurilo", "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { - "message": "Disreputable", + "message": "Malbona reputacio", "description": "An actual reason why a page was blocked" }, "cloudPush": { @@ -1248,7 +1248,7 @@ "description": "A context menu entry, present when large media elements have been blocked on the current site" }, "contextMenuViewSource": { - "message": "Vidi fontkodon...", + "message": "Vidi fontkodon…", "description": "A context menu entry, to view the source code of the target resource" }, "shortcutCapturePlaceholder": { @@ -1304,7 +1304,7 @@ "description": "Summary of number of errors as reported by the linter " }, "unprocessedRequestTooltip": { - "message": "Could not filter properly at browser launch. Reload the page to ensure proper filtering.", + "message": "Ne povas filtri ĝuste kiam la retumilo komenciĝis.\nReŝargu la paĝon por certigi ĝustan filtradon.", "description": "A warning which will appear in the popup panel if needed" }, "dummy": { diff --git a/src/_locales/es/messages.json b/src/_locales/es/messages.json index 56f4d164cb3c7..4b187c152f275 100644 --- a/src/_locales/es/messages.json +++ b/src/_locales/es/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Reglas locales: las reglas en esta columna se aplican solo al sitio actual.\nLas reglas locales anulan las reglas globales.", + "message": "Reglas locales: las reglas en esta columna se aplican solo al sitio actual.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { diff --git a/src/_locales/et/messages.json b/src/_locales/et/messages.json index 74a4a61d32d83..2da28a7477a45 100644 --- a/src/_locales/et/messages.json +++ b/src/_locales/et/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Kohalikud reeglid: selle veeru reeglid kehtivad ainult praegusele saidile.\nKohalikud reeglid kirjutavad üldised reeglid üle.", + "message": "Kohalikud reeglid: selle veeru reeglid kehtivad ainult praegusele saidile.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { diff --git a/src/_locales/eu/messages.json b/src/_locales/eu/messages.json index 1a097a0f133bb..c8ca9a173dd8e 100644 --- a/src/_locales/eu/messages.json +++ b/src/_locales/eu/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Tokiko arauak: Zutabe hau soilik uneko gunean aplikatuko diren arauentzat da. Tokiko arauek arau orokorrak gainidazten dituzte.", + "message": "Tokiko arauak: Zutabe hau soilik uneko gunean aplikatuko diren arauentzat da.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -480,7 +480,7 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "Malware domeinuak", + "message": "Malwarearen aurkako babesa, segurtasuna", "description": "Filter lists section name" }, "3pGroupSocial": { @@ -1008,7 +1008,7 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "Software kaltegarrietara eta phishing-era darama", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { @@ -1180,19 +1180,19 @@ "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { - "message": "Reason:", + "message": "Arrazoia:", "description": "The label which prepend the actual reason why a page was blocked" }, "docblockedReasonMalicious": { - "message": "Malicious", + "message": "Gaiztoa", "description": "An actual reason why a page was blocked" }, "docblockedReasonTracker": { - "message": "Tracker", + "message": "Jarraitzailea", "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { - "message": "Disreputable", + "message": "Ospe txarrekoa", "description": "An actual reason why a page was blocked" }, "cloudPush": { diff --git a/src/_locales/fa/messages.json b/src/_locales/fa/messages.json index fc5ea6583aff3..ed68134ea4af2 100644 --- a/src/_locales/fa/messages.json +++ b/src/_locales/fa/messages.json @@ -16,7 +16,7 @@ "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "بمان", + "message": "اینجا بمان", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { @@ -480,7 +480,7 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "دامنه های مخرب", + "message": "محافظت در برابر بدافزار، امنیت", "description": "Filter lists section name" }, "3pGroupSocial": { @@ -768,7 +768,7 @@ "description": "Label to identify a root context field (typically a hostname)" }, "loggerEntryDetailsPartyness": { - "message": "Partyness", + "message": "اول شخص/شخص ثالث", "description": "Label to identify a field providing partyness information" }, "loggerEntryDetailsType": { @@ -1192,7 +1192,7 @@ "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { - "message": "Disreputable", + "message": "غیرقابل اعتماد", "description": "An actual reason why a page was blocked" }, "cloudPush": { diff --git a/src/_locales/fi/messages.json b/src/_locales/fi/messages.json index bd411bc97e685..eb40d0104eaf4 100644 --- a/src/_locales/fi/messages.json +++ b/src/_locales/fi/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Paikalliset säännöt: Sarake säännöille, joita käytetään vain nykyisellä sivustolla.\nPaikalliset säännöt ohittavat yleiset säännöt.", + "message": "Paikalliset säännöt: Sarake säännöille, joita käytetään vain nykyisellä sivustolla.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { diff --git a/src/_locales/fil/messages.json b/src/_locales/fil/messages.json index 3ec47e10ffc92..07f62ef42d1a1 100644 --- a/src/_locales/fil/messages.json +++ b/src/_locales/fil/messages.json @@ -16,7 +16,7 @@ "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "Manatili", + "message": "Manatili rito", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Mga lokal na patakaran: ang hanay na ito ay para sa mga patakarang ipinapatupad sa site site na ito lamang. Mas sinusunod ang mga lokal na patakaran kaysa sa mga pandaigdigang patakaran.", + "message": "Mga lokal na patakaran: ang hanay na ito ay para sa mga patakarang ipinapatupad sa site site na ito lamang.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -480,7 +480,7 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "Mga domain na may malware", + "message": "Proteksyon sa malware, seguridad", "description": "Filter lists section name" }, "3pGroupSocial": { @@ -900,11 +900,11 @@ "description": "Text for button which open an external web page in Support pane" }, "supportReportSpecificButton": { - "message": "Gumawa ng bagong ulat", + "message": "Gumawa ng bagong ulat sa Github", "description": "Text for button which open an external web page in Support pane" }, "supportFindSpecificButton": { - "message": "Maghanap ng mga magkahawig na ulat", + "message": "Maghanap ng katulad ng ulat sa GitHub", "description": "A clickable link in the filter issue reporter section" }, "supportS1H": { @@ -960,7 +960,7 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "Siguraduhing wala pang ibang nakakapag-ulat ng problema mo upang hindi bahain ng trabaho ang mga volunteer.", + "message": "Upang hindi makagambala ng mga volunteer sa mga umuulit na ulat, pakisigurado na hindi pa narereklamo ang iyong isyu. Paalala: Mapapadala sa Github ang origin ng page na ito pagpindot dito.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { diff --git a/src/_locales/fy/messages.json b/src/_locales/fy/messages.json index 6030a4d7bbce8..71a09e45bf113 100644 --- a/src/_locales/fy/messages.json +++ b/src/_locales/fy/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Lokale rigels: dizze kolom is foar rigels dy't allinnich op de aktuele website fan tapassing binne.\nLokale rigels hawwe foarrang op globale rigels.", + "message": "Lokale regels: dizze kolom is foar regels dy’t allinnich op de aktuele website fan tapassing binne.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { diff --git a/src/_locales/gl/messages.json b/src/_locales/gl/messages.json index 4d3b6279087fa..25bd36982c626 100644 --- a/src/_locales/gl/messages.json +++ b/src/_locales/gl/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Reglas locais: esta columna é para as reglas que afectan só a un sitio. As reglas locais anteponse ás globais.", + "message": "Reglas locais: esta columna é para as reglas que afectan só a un sitio.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { diff --git a/src/_locales/gu/messages.json b/src/_locales/gu/messages.json index 488adce2e009d..9f846270425a1 100644 --- a/src/_locales/gu/messages.json +++ b/src/_locales/gu/messages.json @@ -8,15 +8,15 @@ "description": "this will be in the Chrome web store: must be 132 characters or less" }, "dashboardName": { - "message": "uBlock₀ — Dashboard", + "message": "uBlock₀ — ડેશબોર્ડ", "description": "English: uBlock₀ — Dashboard" }, "dashboardUnsavedWarning": { - "message": "ચેતવણી! તમારા ફેરફારો સચવાયેલા નથી ", + "message": "ચેતવણી! તમારા ફેરફારો સચવાયેલા નથી!", "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "રહો\n", + "message": "અહીં રહો", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { @@ -32,7 +32,7 @@ "description": "appears as tab name in dashboard" }, "1pPageName": { - "message": "મારા ફિલ્ટર ", + "message": "મારા ફિલ્ટરો", "description": "appears as tab name in dashboard" }, "rulesPageName": { @@ -40,51 +40,51 @@ "description": "appears as tab name in dashboard" }, "whitelistPageName": { - "message": "Trusted sites", + "message": "વિશ્વસનીય સાઇટ્સ", "description": "appears as tab name in dashboard" }, "shortcutsPageName": { - "message": "Shortcuts", + "message": "શૉર્ટકટ્સ", "description": "appears as tab name in dashboard" }, "statsPageName": { - "message": "uBlock₀ — Logger", + "message": "uBlock₀ — લોગર", "description": "Title for the logger window" }, "aboutPageName": { - "message": "About", + "message": "વિશે", "description": "appears as tab name in dashboard" }, "supportPageName": { - "message": "Support", + "message": "સહાય", "description": "appears as tab name in dashboard" }, "assetViewerPageName": { - "message": "uBlock₀ — Asset viewer", + "message": "uBlock₀ — સંપત્તિ દર્શક", "description": "Title for the asset viewer page" }, "advancedSettingsPageName": { - "message": "Advanced settings", + "message": "અદ્યતન સેટિંગ્સ", "description": "Title for the advanced settings page" }, "popupPowerSwitchInfo": { - "message": "Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page.", + "message": "ક્લિક કરો: આ સાઇટ માટે uBlock₀ ને અક્ષમ/સક્ષમ કરો.\n\nCtrl+ક્લિક: ફક્ત આ પેજ પર uBlock₀ ને અક્ષમ કરો.", "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." }, "popupPowerSwitchInfo1": { - "message": "Click to disable uBlock₀ for this site.\n\nCtrl+click to disable uBlock₀ only on this page.", + "message": "આ સાઇટ માટે uBlock₀ ને અક્ષમ કરવા ક્લિક કરો.\n\nફક્ત આ પેજ પર uBlock₀ ને અક્ષમ કરવા Ctrl+ક્લિક કરો.", "description": "Message to be read by screen readers" }, "popupPowerSwitchInfo2": { - "message": "Click to enable uBlock₀ for this site.", + "message": "આ સાઇટ માટે uBlock₀ ને સક્ષમ કરવા ક્લિક કરો.", "description": "Message to be read by screen readers" }, "popupBlockedRequestPrompt": { - "message": "requests blocked", + "message": "અવરોધિત વિનંતીઓ", "description": "English: requests blocked" }, "popupBlockedOnThisPagePrompt": { - "message": "on this page", + "message": "આ પેજ પર", "description": "English: on this page" }, "popupBlockedStats": { @@ -92,371 +92,371 @@ "description": "Example: 15 (13%)" }, "popupBlockedSinceInstallPrompt": { - "message": "since install", + "message": "ઇન્સ્ટોલ થયા પછીથી", "description": "English: since install" }, "popupOr": { - "message": "or", + "message": "અથવા", "description": "English: or" }, "popupBlockedOnThisPage_v2": { - "message": "Blocked on this page", + "message": "આ પેજ પર અવરોધિત", "description": "For the new mobile-friendly popup design" }, "popupBlockedSinceInstall_v2": { - "message": "Blocked since install", + "message": "ઇન્સ્ટોલ થયા પછીથી અવરોધિત", "description": "For the new mobile-friendly popup design" }, "popupDomainsConnected_v2": { - "message": "Domains connected", + "message": "જોડાયેલા ડોમેન્સ", "description": "For the new mobile-friendly popup design" }, "popupTipDashboard": { - "message": "Open the dashboard", + "message": "ડેશબોર્ડ ખોલો", "description": "English: Click to open the dashboard" }, "popupTipZapper": { - "message": "Enter element zapper mode", + "message": "તત્વ ઝેપર મોડમાં પ્રવેશ કરો", "description": "Tooltip for the element-zapper icon in the popup panel" }, "popupTipPicker": { - "message": "Enter element picker mode", + "message": "તત્વ પીકર મોડમાં પ્રવેશ કરો", "description": "English: Enter element picker mode" }, "popupTipLog": { - "message": "Open the logger", + "message": "લોગર ખોલો", "description": "Tooltip used for the logger icon in the panel" }, "popupTipReport": { - "message": "Report an issue on this website", + "message": "આ વેબસાઇટ પર સમસ્યાની જાણ કરો", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipNoPopups": { - "message": "Toggle the blocking of all popups for this site", + "message": "આ સાઇટ માટે તમામ પોપઅપ્સના અવરોધને ટૉગલ કરો", "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoPopups1": { - "message": "Click to block all popups on this site", + "message": "આ સાઇટ પર તમામ પોપઅપ્સ અવરોધિત કરવા ક્લિક કરો", "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoPopups2": { - "message": "Click to no longer block all popups on this site", + "message": "આ સાઇટ પર તમામ પોપઅપ્સ હવે અવરોધિત ન કરવા ક્લિક કરો", "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoLargeMedia": { - "message": "Toggle the blocking of large media elements for this site", + "message": "આ સાઇટ માટે મોટા મીડિયા તત્વોના અવરોધને ટૉગલ કરો", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoLargeMedia1": { - "message": "Click to block large media elements on this site", + "message": "આ સાઇટ પર મોટા મીડિયા તત્વો અવરોધિત કરવા ક્લિક કરો", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoLargeMedia2": { - "message": "Click to no longer block large media elements on this site", + "message": "આ સાઇટ પર મોટા મીડિયા તત્વો હવે અવરોધિત ન કરવા ક્લિક કરો", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoCosmeticFiltering": { - "message": "Toggle cosmetic filtering for this site", + "message": "આ સાઇટ માટે કોસ્મેટિક ફિલ્ટરિંગ ટૉગલ કરો", "description": "Tooltip for the no-cosmetic-filtering per-site switch" }, "popupTipNoCosmeticFiltering1": { - "message": "Click to disable cosmetic filtering on this site", + "message": "આ સાઇટ પર કોસ્મેટિક ફિલ્ટરિંગ અક્ષમ કરવા ક્લિક કરો", "description": "Tooltip for the no-cosmetic-filtering per-site switch" }, "popupTipNoCosmeticFiltering2": { - "message": "Click to enable cosmetic filtering on this site", + "message": "આ સાઇટ પર કોસ્મેટિક ફિલ્ટરિંગ સક્ષમ કરવા ક્લિક કરો", "description": "Tooltip for the no-cosmetic-filtering per-site switch" }, "popupTipNoRemoteFonts": { - "message": "Toggle the blocking of remote fonts for this site", + "message": "આ સાઇટ માટે રિમોટ ફોન્ટ્સના અવરોધને ટૉગલ કરો", "description": "Tooltip for the no-remote-fonts per-site switch" }, "popupTipNoRemoteFonts1": { - "message": "Click to block remote fonts on this site", + "message": "આ સાઇટ પર રિમોટ ફોન્ટ્સ અવરોધિત કરવા ક્લિક કરો", "description": "Tooltip for the no-remote-fonts per-site switch" }, "popupTipNoRemoteFonts2": { - "message": "Click to no longer block remote fonts on this site", + "message": "આ સાઇટ પર રિમોટ ફોન્ટ્સ હવે અવરોધિત ન કરવા ક્લિક કરો", "description": "Tooltip for the no-remote-fonts per-site switch" }, "popupTipNoScripting1": { - "message": "Click to disable JavaScript on this site", + "message": "આ સાઇટ પર JavaScript અક્ષમ કરવા ક્લિક કરો", "description": "Tooltip for the no-scripting per-site switch" }, "popupTipNoScripting2": { - "message": "Click to no longer disable JavaScript on this site", + "message": "આ સાઇટ પર JavaScript હવે અક્ષમ ન કરવા ક્લિક કરો", "description": "Tooltip for the no-scripting per-site switch" }, "popupNoPopups_v2": { - "message": "Pop-up windows", + "message": "પોપ-અપ વિન્ડોઝ", "description": "Caption for the no-popups per-site switch" }, "popupNoLargeMedia_v2": { - "message": "Large media elements", + "message": "મોટા મીડિયા તત્વો", "description": "Caption for the no-large-media per-site switch" }, "popupNoCosmeticFiltering_v2": { - "message": "Cosmetic filtering", + "message": "કોસ્મેટિક ફિલ્ટરિંગ", "description": "Caption for the no-cosmetic-filtering per-site switch" }, "popupNoRemoteFonts_v2": { - "message": "Remote fonts", + "message": "રિમોટ ફોન્ટ્સ", "description": "Caption for the no-remote-fonts per-site switch" }, "popupNoScripting_v2": { - "message": "JavaScript", + "message": "જાવાસ્ક્રિપ્ટ", "description": "Caption for the no-scripting per-site switch" }, "popupMoreButton_v2": { - "message": "More", + "message": "વધુ", "description": "Label to be used to show popup panel sections" }, "popupLessButton_v2": { - "message": "Less", + "message": "ઓછું", "description": "Label to be used to hide popup panel sections" }, "popupTipGlobalRules": { - "message": "Global rules: this column is for rules which apply to all sites.", + "message": "વૈશ્વિક નિયમો: આ કૉલમ એવા નિયમો માટે છે જે તમામ સાઇટ્સ પર લાગુ પડે છે.", "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Local rules: this column is for rules which apply to the current site only.", + "message": "સ્થાનિક નિયમો: આ કૉલમ ફક્ત વર્તમાન સાઇટ પર લાગુ પડતા નિયમો માટે છે.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { - "message": "Click to make your changes permanent.", + "message": "તમારા ફેરફારોને કાયમી બનાવવા ક્લિક કરો.", "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." }, "popupTipRevertRules": { - "message": "Click to revert your changes.", + "message": "તમારા ફેરફારોને પૂર્વવત્ કરવા ક્લિક કરો.", "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." }, "popupAnyRulePrompt": { - "message": "all", + "message": "બધા", "description": "" }, "popupImageRulePrompt": { - "message": "images", + "message": "છબીઓ", "description": "" }, "popup3pAnyRulePrompt": { - "message": "3rd-party", + "message": "તૃતીય-પક્ષ", "description": "" }, "popup3pPassiveRulePrompt": { - "message": "3rd-party CSS/images", + "message": "તૃતીય-પક્ષ CSS/છબીઓ", "description": "" }, "popupInlineScriptRulePrompt": { - "message": "inline scripts", + "message": "ઇનલાઇન સ્ક્રિપ્ટો", "description": "" }, "popup1pScriptRulePrompt": { - "message": "1st-party scripts", + "message": "પ્રથમ-પક્ષ સ્ક્રિપ્ટો", "description": "" }, "popup3pScriptRulePrompt": { - "message": "3rd-party scripts", + "message": "તૃતીય-પક્ષ સ્ક્રિપ્ટો", "description": "" }, "popup3pFrameRulePrompt": { - "message": "3rd-party frames", + "message": "તૃતીય-પક્ષ ફ્રેમ્સ", "description": "" }, "popupHitDomainCountPrompt": { - "message": "domains connected", + "message": "જોડાયેલા ડોમેન્સ", "description": "appears in popup" }, "popupHitDomainCount": { - "message": "{{count}} out of {{total}}", + "message": "{{total}} માંથી {{count}}", "description": "appears in popup" }, "popupVersion": { - "message": "Version", + "message": "આવૃત્તિ", "description": "Example of use: Version 1.26.4" }, "popup3pScriptFilter": { - "message": "script", + "message": "સ્ક્રિપ્ટ", "description": "Appears as an option to filter out firewall rows" }, "popup3pFrameFilter": { - "message": "frame", + "message": "ફ્રેમ", "description": "Appears as an option to filter out firewall rows" }, "pickerCreate": { - "message": "Create", + "message": "બનાવો", "description": "English: Create" }, "pickerPick": { - "message": "Pick", + "message": "પસંદ કરો", "description": "English: Pick" }, "pickerQuit": { - "message": "Quit", + "message": "બહાર નીકળો", "description": "English: Quit" }, "pickerPreview": { - "message": "Preview", + "message": "પૂર્વદર્શન", "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" }, "pickerNetFilters": { - "message": "Network filters", + "message": "નેટવર્ક ફિલ્ટરો", "description": "English: header for a type of filter in the element picker dialog" }, "pickerCosmeticFilters": { - "message": "Cosmetic filters", + "message": "કોસ્મેટિક ફિલ્ટરો", "description": "English: Cosmetic filters" }, "pickerCosmeticFiltersHint": { - "message": "Click, Ctrl-click", + "message": "ક્લિક કરો, Ctrl-ક્લિક કરો", "description": "English: Click, Ctrl-click" }, "pickerContextMenuEntry": { - "message": "Block element…", + "message": "તત્વ અવરોધિત કરો…", "description": "An entry in the browser's contextual menu" }, "settingsCollapseBlockedPrompt": { - "message": "Hide placeholders of blocked elements", + "message": "અવરોધિત તત્વોના પ્લેસહોલ્ડર્સ છુપાવો", "description": "English: Hide placeholders of blocked elements" }, "settingsIconBadgePrompt": { - "message": "Show the number of blocked requests on the icon", + "message": "આઇકન પર અવરોધિત વિનંતીઓની સંખ્યા બતાવો", "description": "English: Show the number of blocked requests on the icon" }, "settingsTooltipsPrompt": { - "message": "Disable tooltips", + "message": "ટૂલટિપ્સ અક્ષમ કરો", "description": "A checkbox in the Settings pane" }, "settingsContextMenuPrompt": { - "message": "Make use of context menu where appropriate", + "message": "જ્યાં યોગ્ય હોય ત્યાં સંદર્ભ મેનુનો ઉપયોગ કરો", "description": "English: Make use of context menu where appropriate" }, "settingsColorBlindPrompt": { - "message": "Color-blind friendly", + "message": "રંગ-અંધ મૈત્રીપૂર્ણ", "description": "English: Color-blind friendly" }, "settingsAppearance": { - "message": "Appearance", + "message": "દેખાવ", "description": "Section for controlling user interface appearance" }, "settingsThemeLabel": { - "message": "Theme", + "message": "થીમ", "description": "Label for checkbox to enable a custom dark theme" }, "settingsThemeAccent0Label": { - "message": "Custom accent color", + "message": "કસ્ટમ એક્સેન્ટ રંગ", "description": "Label for checkbox to pick an accent color" }, "settingsCloudStorageEnabledPrompt": { - "message": "Enable cloud storage support", + "message": "ક્લાઉડ સ્ટોરેજ સપોર્ટ સક્ષમ કરો", "description": "" }, "settingsAdvancedUserPrompt": { - "message": "I am an advanced user", + "message": "હું અદ્યતન વપરાશકર્તા છું", "description": "Checkbox to let user access advanced, technical features" }, "settingsPrefetchingDisabledPrompt": { - "message": "Disable pre-fetching (to prevent any connection for blocked network requests)", + "message": "પ્રી-ફેચિંગ અક્ષમ કરો (અવરોધિત નેટવર્ક વિનંતીઓ માટે કોઈપણ કનેક્શનને રોકવા માટે)", "description": "English: " }, "settingsHyperlinkAuditingDisabledPrompt": { - "message": "Disable hyperlink auditing", + "message": "હાઇપરલિંક ઓડિટિંગ અક્ષમ કરો", "description": "English: " }, "settingsWebRTCIPAddressHiddenPrompt": { - "message": "Prevent WebRTC from leaking local IP addresses", + "message": "WebRTC ને સ્થાનિક IP સરનામાં લીક કરતા અટકાવો", "description": "English: " }, "settingPerSiteSwitchGroup": { - "message": "Default behavior", + "message": "મૂળભૂત વર્તન", "description": "" }, "settingPerSiteSwitchGroupSynopsis": { - "message": "These default behaviors can be overridden on a per-site basis", + "message": "આ મૂળભૂત વર્તણૂકોને સાઇટ-દીઠ ધોરણે ઓવરરાઇડ કરી શકાય છે", "description": "" }, "settingsNoCosmeticFilteringPrompt": { - "message": "Disable cosmetic filtering", + "message": "કોસ્મેટિક ફિલ્ટરિંગ અક્ષમ કરો", "description": "" }, "settingsNoLargeMediaPrompt": { - "message": "Block media elements larger than {{input}} KB", + "message": "{{input}} KB કરતાં મોટા મીડિયા તત્વો અવરોધિત કરો", "description": "" }, "settingsNoRemoteFontsPrompt": { - "message": "Block remote fonts", + "message": "રિમોટ ફોન્ટ્સ અવરોધિત કરો", "description": "" }, "settingsNoScriptingPrompt": { - "message": "Disable JavaScript", + "message": "JavaScript અક્ષમ કરો", "description": "The default state for the per-site no-scripting switch" }, "settingsNoCSPReportsPrompt": { - "message": "Block CSP reports", + "message": "CSP રિપોર્ટ્સ અવરોધિત કરો", "description": "background information: https://github.com/gorhill/uBlock/issues/3150" }, "settingsUncloakCnamePrompt": { - "message": "Uncloak canonical names", + "message": "કેનોનિકલ નામો અનક્લોક કરો", "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" }, "settingsAdvanced": { - "message": "Advanced", + "message": "અદ્યતન", "description": "Section for controlling advanced-user settings" }, "settingsAdvancedSynopsis": { - "message": "Features suitable only for technical users", + "message": "ફક્ત તકનીકી વપરાશકર્તાઓ માટે યોગ્ય સુવિધાઓ", "description": "Description of section controlling advanced-user settings" }, "settingsAdvancedUserSettings": { - "message": "advanced settings", + "message": "અદ્યતન સેટિંગ્સ", "description": "For the tooltip of a link which gives access to advanced settings" }, "settingsLastRestorePrompt": { - "message": "Last restore:", + "message": "છેલ્લું પુનઃસ્થાપન:", "description": "English: Last restore:" }, "settingsLastBackupPrompt": { - "message": "Last backup:", + "message": "છેલ્લું બેકઅપ:", "description": "English: Last backup:" }, "3pListsOfBlockedHostsPrompt": { - "message": "{{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:", + "message": "માંથી {{netFilterCount}} નેટવર્ક ફિલ્ટરો + {{cosmeticFilterCount}} કોસ્મેટિક ફિલ્ટરો:", "description": "Appears at the top of the _3rd-party filters_ pane" }, "3pListsOfBlockedHostsPerListStats": { - "message": "{{used}} used out of {{total}}", + "message": "{{total}} માંથી {{used}} વપરાયેલ", "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "3pAutoUpdatePrompt1": { - "message": "Auto-update filter lists", + "message": "ફિલ્ટર યાદીઓનું સ્વયં-અપડેટ કરો", "description": "A checkbox in the _3rd-party filters_ pane" }, "3pUpdateNow": { - "message": "Update now", + "message": "હવે અપડેટ કરો", "description": "A button in the in the _3rd-party filters_ pane" }, "3pPurgeAll": { - "message": "Purge all caches", + "message": "બધા કૅશ શુદ્ધ કરો", "description": "A button in the in the _3rd-party filters_ pane" }, "3pParseAllABPHideFiltersPrompt1": { - "message": "Parse and enforce cosmetic filters", + "message": "કોસ્મેટિક ફિલ્ટરોને પાર્સ અને લાગુ કરો", "description": "English: Parse and enforce Adblock+ element hiding filters." }, "3pParseAllABPHideFiltersInfo": { - "message": "Cosmetic filters serve to hide elements in a web page which are deemed to be a visual nuisance, and which can't be blocked by the network request-based filtering engines.", + "message": "કોસ્મેટિક ફિલ્ટરો વેબ પેજમાં એવા તત્વોને છુપાવવા માટે સેવા આપે છે જે દ્રશ્ય ઉપદ્રવ માનવામાં આવે છે, અને જેને નેટવર્ક વિનંતી-આધારિત ફિલ્ટરિંગ એન્જિન દ્વારા અવરોધિત કરી શકાતા નથી.", "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." }, "3pIgnoreGenericCosmeticFilters": { - "message": "Ignore generic cosmetic filters", + "message": "સામાન્ય કોસ્મેટિક ફિલ્ટરોને અવગણો", "description": "This will cause uBO to ignore all generic cosmetic filters." }, "3pIgnoreGenericCosmeticFiltersInfo": { - "message": "Generic cosmetic filters are those cosmetic filters which are meant to apply on all web sites. Enabling this option will eliminate the memory and CPU overhead added to web pages as a result of handling generic cosmetic filters.\n\nIt is recommended to enable this option on less powerful devices.", + "message": "સામાન્ય કોસ્મેટિક ફિલ્ટરો તે કોસ્મેટિક ફિલ્ટરો છે જે તમામ વેબ સાઇટ્સ પર લાગુ કરવા માટે છે. આ વિકલ્પને સક્ષમ કરવાથી સામાન્ય કોસ્મેટિક ફિલ્ટરોને હેન્ડલ કરવાના પરિણામે વેબ પેજોમાં ઉમેરાયેલ મેમરી અને CPU ઓવરહેડ દૂર થશે.\n\nઓછા શક્તિશાળી ઉપકરણો પર આ વિકલ્પને સક્ષમ કરવાની ભલામણ કરવામાં આવે છે.", "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." }, "3pSuspendUntilListsAreLoaded": { - "message": "Suspend network activity until all filter lists are loaded", + "message": "તમામ ફિલ્ટર યાદીઓ લોડ ન થાય ત્યાં સુધી નેટવર્ક પ્રવૃત્તિ સ્થગિત કરો", "description": "A checkbox in the 'Filter lists' pane" }, "3pListsOfBlockedHostsHeader": { @@ -464,95 +464,95 @@ "description": "English: Lists of blocked hosts" }, "3pApplyChanges": { - "message": "Apply changes", + "message": "ફેરફારો લાગુ કરો", "description": "English: Apply changes" }, "3pGroupDefault": { - "message": "Built-in", + "message": "બિલ્ટ-ઇન", "description": "Filter lists section name" }, "3pGroupAds": { - "message": "Ads", + "message": "જાહેરાતો", "description": "Filter lists section name" }, "3pGroupPrivacy": { - "message": "Privacy", + "message": "ગોપનીયતા", "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "Malware protection, security", + "message": "માલવેર સુરક્ષા, સુરક્ષા", "description": "Filter lists section name" }, "3pGroupSocial": { - "message": "Social widgets", + "message": "સામાજિક વિજેટ્સ", "description": "Filter lists section name" }, "3pGroupCookies": { - "message": "Cookie notices", + "message": "કૂકી સૂચનાઓ", "description": "Filter lists section name" }, "3pGroupAnnoyances": { - "message": "Annoyances", + "message": "ઉપદ્રવો", "description": "Filter lists section name" }, "3pGroupMultipurpose": { - "message": "Multipurpose", + "message": "બહુહેતુક", "description": "Filter lists section name" }, "3pGroupRegions": { - "message": "Regions, languages", + "message": "પ્રદેશો, ભાષાઓ", "description": "Filter lists section name" }, "3pGroupCustom": { - "message": "Custom", + "message": "કસ્ટમ", "description": "Filter lists section name" }, "3pImport": { - "message": "Import…", + "message": "આયાત કરો…", "description": "The label for the checkbox used to import external filter lists" }, "3pExternalListsHint": { - "message": "One URL per line. Invalid URLs will be silently ignored.", + "message": "એક લીટી દીઠ એક URL. અયોગ્ય URL ને શાંતિથી અવગણવામાં આવશે.", "description": "Short information about how to use the textarea to import external filter lists by URL" }, "3pExternalListObsolete": { - "message": "Out of date.", + "message": "જૂનું છે.", "description": "used as a tooltip for the out-of-date icon beside a list" }, "3pViewContent": { - "message": "view content", + "message": "સામગ્રી જુઓ", "description": "used as a tooltip for eye icon beside a list" }, "3pLastUpdate": { - "message": "Last update: {{ago}}.\nClick to force an update.", + "message": "છેલ્લું અપડેટ: {{ago}}.\nઅપડેટ ફરજિયાત કરવા ક્લિક કરો.", "description": "used as a tooltip for the clock icon beside a list" }, "3pUpdating": { - "message": "Updating…", + "message": "અપડેટ થઈ રહ્યું છે…", "description": "used as a tooltip for the spinner icon beside a list" }, "3pNetworkError": { - "message": "A network error prevented the resource from being updated.", + "message": "નેટવર્ક ભૂલને કારણે સંસાધન અપડેટ થઈ શક્યું નહીં.", "description": "used as a tooltip for error icon beside a list" }, "1pTrustWarning": { - "message": "Do not add filters from untrusted sources.", + "message": "અવિશ્વસનીય સ્ત્રોતોમાંથી ફિલ્ટરો ઉમેરશો નહીં.", "description": "Warning against copy-pasting filters from random sources" }, "1pEnableMyFiltersLabel": { - "message": "Enable my custom filters", + "message": "મારા કસ્ટમ ફિલ્ટરો સક્ષમ કરો", "description": "Label for the checkbox use to enable/disable 'My filters' list" }, "1pTrustMyFiltersLabel": { - "message": "Allow custom filters requiring trust", + "message": "વિશ્વાસની જરૂર હોય તેવા કસ્ટમ ફિલ્ટરોને મંજૂરી આપો", "description": "Label for the checkbox use to trust the content of 'My filters' list" }, "1pImport": { - "message": "Import and append…", + "message": "આયાત કરો અને ઉમેરો…", "description": "Button in the 'My filters' pane" }, "1pExport": { - "message": "Export…", + "message": "નિકાસ કરો…", "description": "Button in the 'My filters' pane" }, "1pExportFilename": { @@ -560,43 +560,43 @@ "description": "English: my-ublock-static-filters_{{datetime}}.txt" }, "1pApplyChanges": { - "message": "Apply changes", + "message": "ફેરફારો લાગુ કરો", "description": "English: Apply changes" }, "rulesPermanentHeader": { - "message": "Permanent rules", + "message": "કાયમી નિયમો", "description": "header" }, "rulesTemporaryHeader": { - "message": "Temporary rules", + "message": "કામચલાઉ નિયમો", "description": "header" }, "rulesRevert": { - "message": "Revert", + "message": "પૂર્વવત્ કરો", "description": "This will remove all temporary rules" }, "rulesCommit": { - "message": "Commit", + "message": "સ્થાયી કરો", "description": "This will persist temporary rules" }, "rulesEdit": { - "message": "Edit", + "message": "ફેરફાર કરો", "description": "Will enable manual-edit mode (textarea)" }, "rulesEditSave": { - "message": "Save", + "message": "સાચવો", "description": "Will save manually-edited content and exit manual-edit mode" }, "rulesEditDiscard": { - "message": "Discard", + "message": "કાઢી નાખો", "description": "Will discard manually-edited content and exit manual-edit mode" }, "rulesImport": { - "message": "Import from file…", + "message": "ફાઇલમાંથી આયાત કરો…", "description": "" }, "rulesExport": { - "message": "Export to file…", + "message": "ફાઇલમાં નિકાસ કરો…", "description": "Button in the 'My rules' pane" }, "rulesDefaultFileName": { @@ -604,39 +604,39 @@ "description": "default file name to use" }, "rulesHint": { - "message": "List of your dynamic filtering rules.", + "message": "તમારા ડાયનેમિક ફિલ્ટરિંગ નિયમોની યાદી.", "description": "English: List of your dynamic filtering rules." }, "rulesFormatHint": { - "message": "Rule syntax: source destination type action (full documentation).", + "message": "નિયમ સિન્ટેક્સ: સ્રોત ગંતવ્ય પ્રકાર ક્રિયા (સંપૂર્ણ દસ્તાવેજીકરણ).", "description": "English: dynamic rule syntax and full documentation." }, "rulesSort": { - "message": "Sort:", + "message": "ક્રમ આપો:", "description": "English: label for sort option." }, "rulesSortByType": { - "message": "Rule type", + "message": "નિયમ પ્રકાર", "description": "English: a sort option for list of rules." }, "rulesSortBySource": { - "message": "Source", + "message": "સ્રોત", "description": "English: a sort option for list of rules." }, "rulesSortByDestination": { - "message": "Destination", + "message": "ગંતવ્ય", "description": "English: a sort option for list of rules." }, "whitelistPrompt": { - "message": "The trusted site directives dictate on which web pages uBlock Origin should be disabled. One entry per line.", + "message": "વિશ્વસનીય સાઇટ નિર્દેશો નક્કી કરે છે કે કયા વેબ પેજો પર uBlock Origin અક્ષમ હોવું જોઈએ. એક લીટી દીઠ એક એન્ટ્રી.", "description": "A concise description of the 'Trusted sites' pane." }, "whitelistImport": { - "message": "Import and append…", + "message": "આયાત કરો અને ઉમેરો…", "description": "Button in the 'Trusted sites' pane" }, "whitelistExport": { - "message": "Export…", + "message": "નિકાસ કરો…", "description": "Button in the 'Trusted sites' pane" }, "whitelistExportFilename": { @@ -644,15 +644,15 @@ "description": "The default filename to use for import/export purpose" }, "whitelistApply": { - "message": "Apply changes", + "message": "ફેરફારો લાગુ કરો", "description": "English: Apply changes" }, "logRequestsHeaderType": { - "message": "Type", + "message": "પ્રકાર", "description": "English: Type" }, "logRequestsHeaderDomain": { - "message": "Domain", + "message": "ડોમેન", "description": "English: Domain" }, "logRequestsHeaderURL": { @@ -660,63 +660,63 @@ "description": "English: URL" }, "logRequestsHeaderFilter": { - "message": "Filter", + "message": "ફિલ્ટર", "description": "English: Filter" }, "logAll": { - "message": "All", + "message": "બધા", "description": "Appears in the logger's tab selector" }, "logBehindTheScene": { - "message": "Tabless", + "message": "ટેબલેસ", "description": "Pretty name for behind-the-scene network requests" }, "loggerCurrentTab": { - "message": "Current tab", + "message": "વર્તમાન ટૅબ", "description": "Appears in the logger's tab selector" }, "loggerReloadTip": { - "message": "Reload the tab content", + "message": "ટૅબ સામગ્રી ફરીથી લોડ કરો", "description": "Tooltip for the reload button in the logger page" }, "loggerDomInspectorTip": { - "message": "Toggle the DOM inspector", + "message": "DOM ઇન્સ્પેક્ટર ટૉગલ કરો", "description": "Tooltip for the DOM inspector button in the logger page" }, "loggerPopupPanelTip": { - "message": "Toggle the popup panel", + "message": "પોપઅપ પેનલ ટૉગલ કરો", "description": "Tooltip for the popup panel button in the logger page" }, "loggerInfoTip": { - "message": "uBlock Origin wiki: The logger", + "message": "uBlock Origin વિકિ: લોગર", "description": "Tooltip for the top-right info label in the logger page" }, "loggerClearTip": { - "message": "Clear logger", + "message": "લોગર સાફ કરો", "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" }, "loggerPauseTip": { - "message": "Pause logger (discard all incoming data)", + "message": "લોગર થોભાવો (તમામ આવતો ડેટા કાઢી નાખો)", "description": "Tooltip for the pause button in the logger page" }, "loggerUnpauseTip": { - "message": "Unpause logger", + "message": "લોગર ફરી શરૂ કરો", "description": "Tooltip for the play button in the logger page" }, "loggerRowFiltererButtonTip": { - "message": "Toggle logger filtering", + "message": "લોગર ફિલ્ટરિંગ ટૉગલ કરો", "description": "Tooltip for the row filterer button in the logger page" }, "logFilterPrompt": { - "message": "filter logger content", + "message": "લોગર સામગ્રી ફિલ્ટર કરો", "description": "Placeholder string for logger output filtering input field" }, "loggerRowFiltererBuiltinTip": { - "message": "Logger filtering options", + "message": "લોગર ફિલ્ટરિંગ વિકલ્પો", "description": "Tooltip for the button to bring up logger output filtering options" }, "loggerRowFiltererBuiltinNot": { - "message": "Not", + "message": "નહીં", "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltinEventful": { @@ -724,55 +724,55 @@ "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" }, "loggerRowFiltererBuiltinBlocked": { - "message": "blocked", + "message": "અવરોધિત", "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltinAllowed": { - "message": "allowed", + "message": "મંજૂર", "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltinModified": { - "message": "modified", + "message": "સંશોધિત", "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltin1p": { - "message": "1st-party", + "message": "પ્રથમ-પક્ષ", "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltin3p": { - "message": "3rd-party", + "message": "તૃતીય-પક્ષ", "description": "A keyword in the built-in row filtering expression" }, "loggerEntryDetailsHeader": { - "message": "Details", + "message": "વિગતો", "description": "Small header to identify the 'Details' pane for a specific logger entry" }, "loggerEntryDetailsFilter": { - "message": "Filter", + "message": "ફિલ્ટર", "description": "Label to identify a filter field" }, "loggerEntryDetailsFilterList": { - "message": "Filter list", + "message": "ફિલ્ટર યાદી", "description": "Label to identify a filter list field" }, "loggerEntryDetailsRule": { - "message": "Rule", + "message": "નિયમ", "description": "Label to identify a rule field" }, "loggerEntryDetailsContext": { - "message": "Context", + "message": "સંદર્ભ", "description": "Label to identify a context field (typically a hostname)" }, "loggerEntryDetailsRootContext": { - "message": "Root context", + "message": "રૂટ સંદર્ભ", "description": "Label to identify a root context field (typically a hostname)" }, "loggerEntryDetailsPartyness": { - "message": "Partyness", + "message": "પાર્ટીનેસ", "description": "Label to identify a field providing partyness information" }, "loggerEntryDetailsType": { - "message": "Type", + "message": "પ્રકાર", "description": "Label to identify the type of an entry" }, "loggerEntryDetailsURL": { @@ -780,283 +780,283 @@ "description": "Label to identify the URL of an entry" }, "loggerURLFilteringHeader": { - "message": "URL rule", + "message": "URL નિયમ", "description": "Small header to identify the dynamic URL filtering section" }, "loggerURLFilteringContextLabel": { - "message": "Context:", + "message": "સંદર્ભ:", "description": "Label for the context selector" }, "loggerURLFilteringTypeLabel": { - "message": "Type:", + "message": "પ્રકાર:", "description": "Label for the type selector" }, "loggerStaticFilteringHeader": { - "message": "Static filter", + "message": "સ્થિર ફિલ્ટર", "description": "Small header to identify the static filtering section" }, "loggerStaticFilteringSentence": { - "message": "{{action}} network requests of {{type}} {{br}}which URL address matches {{url}} {{br}}and which originates {{origin}},{{br}}{{importance}} there is a matching exception filter.", + "message": "{{action}} નેટવર્ક વિનંતીઓ {{type}} {{br}}જેનું URL સરનામું {{url}} સાથે મેળ ખાય છે {{br}}અને જે {{origin}} માંથી ઉદ્ભવે છે,{{br}}{{importance}} ત્યાં એક મેળ ખાતું અપવાદ ફિલ્ટર છે.", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartBlock": { - "message": "Block", + "message": "અવરોધિત કરો", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartAllow": { - "message": "Allow", + "message": "મંજૂરી આપો", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartType": { - "message": "type “{{type}}”", + "message": "પ્રકાર “{{type}}”", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartAnyType": { - "message": "any type", + "message": "કોઈપણ પ્રકાર", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartOrigin": { - "message": "from “{{origin}}”", + "message": "“{{origin}}” માંથી", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartAnyOrigin": { - "message": "from anywhere", + "message": "ગમે ત્યાંથી", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartNotImportant": { - "message": "except when", + "message": "સિવાય કે", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartImportant": { - "message": "even if", + "message": "જો કે", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringFinderSentence1": { - "message": "Static filter {{filter}} found in:", + "message": "સ્થિર ફિલ્ટર {{filter}} આમાં મળ્યું:", "description": "Below this sentence, the filter list(s) in which the filter was found" }, "loggerStaticFilteringFinderSentence2": { - "message": "Static filter could not be found in any of the currently enabled filter lists", + "message": "હાલમાં સક્ષમ કરેલી કોઈપણ ફિલ્ટર યાદીમાં સ્થિર ફિલ્ટર મળી શક્યું નથી", "description": "Message to show when a filter cannot be found in any filter lists" }, "loggerSettingDiscardPrompt": { - "message": "Logger entries which do not fulfill all three conditions below will be automatically discarded:", + "message": "નીચેની ત્રણેય શરતો પૂરી ન કરતી લોગર એન્ટ્રીઓ આપમેળે કાઢી નાખવામાં આવશે:", "description": "Logger setting: A sentence to describe the purpose of the settings below" }, "loggerSettingPerEntryMaxAge": { - "message": "Preserve entries from the last {{input}} minutes", + "message": "છેલ્લી {{input}} મિનિટની એન્ટ્રીઓ સાચવો", "description": "A logger setting" }, "loggerSettingPerTabMaxLoads": { - "message": "Preserve at most {{input}} page loads per tab", + "message": "દરેક ટૅબ દીઠ વધુમાં વધુ {{input}} પેજ લોડ સાચવો", "description": "A logger setting" }, "loggerSettingPerTabMaxEntries": { - "message": "Preserve at most {{input}} entries per tab", + "message": "દરેક ટૅબ દીઠ વધુમાં વધુ {{input}} એન્ટ્રીઓ સાચવો", "description": "A logger setting" }, "loggerSettingPerEntryLineCount": { - "message": "Use {{input}} lines per entry in vertically expanded mode", + "message": "ઊભી રીતે વિસ્તૃત મોડમાં દરેક એન્ટ્રી માટે {{input}} લીટીઓનો ઉપયોગ કરો", "description": "A logger setting" }, "loggerSettingHideColumnsPrompt": { - "message": "Hide columns:", + "message": "કૉલમ્સ છુપાવો:", "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" }, "loggerSettingHideColumnTime": { - "message": "{{input}} Time", + "message": "{{input}} સમય", "description": "A label for the time column" }, "loggerSettingHideColumnFilter": { - "message": "{{input}} Filter/rule", + "message": "{{input}} ફિલ્ટર/નિયમ", "description": "A label for the filter or rule column" }, "loggerSettingHideColumnContext": { - "message": "{{input}} Context", + "message": "{{input}} સંદર્ભ", "description": "A label for the context column" }, "loggerSettingHideColumnPartyness": { - "message": "{{input}} Partyness", + "message": "{{input}} પાર્ટીનેસ", "description": "A label for the partyness column" }, "loggerExportFormatList": { - "message": "List", + "message": "યાદી", "description": "Label for radio-button to pick export format" }, "loggerExportFormatTable": { - "message": "Table", + "message": "કોષ્ટક", "description": "Label for radio-button to pick export format" }, "loggerExportEncodePlain": { - "message": "Plain", + "message": "સાદું", "description": "Label for radio-button to pick export text format" }, "loggerExportEncodeMarkdown": { - "message": "Markdown", + "message": "માર્કડાઉન", "description": "Label for radio-button to pick export text format" }, "supportOpenButton": { - "message": "Open", + "message": "ખોલો", "description": "Text for button which open an external web page in Support pane" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "GitHub પર નવો રિપોર્ટ બનાવો", "description": "Text for button which open an external web page in Support pane" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "GitHub પર સમાન રિપોર્ટ્સ શોધો", "description": "A clickable link in the filter issue reporter section" }, "supportS1H": { - "message": "Documentation", + "message": "દસ્તાવેજીકરણ", "description": "Header of 'Documentation' section in Support pane" }, "supportS1P1": { - "message": "Read the documentation at uBlock/wiki to learn about all of uBlock Origin's features.", + "message": "uBlock Origin ની તમામ સુવિધાઓ વિશે જાણવા uBlock/wiki પર દસ્તાવેજીકરણ વાંચો.", "description": "First paragraph of 'Documentation' section in Support pane" }, "supportS2H": { - "message": "Questions and support", + "message": "પ્રશ્નો અને સહાય", "description": "Header of 'Questions and support' section in Support pane" }, "supportS2P1": { - "message": "Answers to questions and other kinds of help support is provided on the subreddit /r/uBlockOrigin.", + "message": "પ્રશ્નોના જવાબો અને અન્ય પ્રકારની સહાય સબરેડિટ /r/uBlockOrigin પર પૂરી પાડવામાં આવે છે.", "description": "First paragraph of 'Questions and support' section in Support pane" }, "supportS3H": { - "message": "Filter issues/website is broken", + "message": "ફિલ્ટર સમસ્યાઓ/વેબસાઇટ તૂટેલી છે", "description": "Header of 'Filter issues' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "ચોક્કસ વેબસાઇટ્સ સાથે ફિલ્ટર સમસ્યાઓની જાણ uBlockOrigin/uAssets ઇશ્યુ ટ્રૅકર પર કરો. GitHub ખાતું જરૂરી છે.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS3P2": { - "message": "Important: Avoid using other similarly-purposed blockers along with uBlock Origin, as this may cause filter issues on specific websites.", + "message": "મહત્વપૂર્ણ: uBlock Origin સાથે સમાન હેતુ ધરાવતા અન્ય અવરોધકોનો ઉપયોગ કરવાનું ટાળો, કારણ કે આ ચોક્કસ વેબસાઇટ્સ પર ફિલ્ટર સમસ્યાઓનું કારણ બની શકે છે.", "description": "Second paragraph of 'Filter issues' section in Support pane" }, "supportS3P3": { - "message": "Tips: Be sure your filter lists are up to date. The logger is the primary tool to diagnose filter-related issues.", + "message": "ટિપ્સ: ખાતરી કરો કે તમારી ફિલ્ટર યાદીઓ અદ્યતન છે. લોગર ફિલ્ટર-સંબંધિત સમસ્યાઓનું નિદાન કરવા માટેનું પ્રાથમિક સાધન છે.", "description": "Third paragraph of 'Filter issues' section in Support pane" }, "supportS4H": { - "message": "Bug report", + "message": "બગ રિપોર્ટ", "description": "Header of 'Bug report' section in Support pane" }, "supportS4P1": { - "message": "Report issues with uBlock Origin itself to the uBlockOrigin/uBlock-issue issue tracker. Requires a GitHub account.", + "message": "uBlock Origin સાથેની સમસ્યાઓની જાણ uBlockOrigin/uBlock-issue ઇશ્યુ ટ્રૅકર પર કરો. GitHub ખાતું જરૂરી છે.", "description": "First paragraph of 'Bug report' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting Information", + "message": "સમસ્યાનિવારણ માહિતી", "description": "Header of 'Troubleshooting Information' section in Support pane" }, "supportS5P1": { - "message": "Below is technical information that might be useful when volunteers are trying to help you solve a problem.", + "message": "નીચે તકનીકી માહિતી છે જે સ્વયંસેવકો તમને સમસ્યા હલ કરવામાં મદદ કરવાનો પ્રયાસ કરી રહ્યા હોય ત્યારે ઉપયોગી થઈ શકે છે.", "description": "First paragraph of 'Troubleshooting Information' section in Support pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "ફિલ્ટર સમસ્યાની જાણ કરો", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "સ્વયંસેવકોને ડુપ્લિકેટ રિપોર્ટ્સથી બોજ ન પડે તે માટે, કૃપા કરીને ચકાસો કે સમસ્યા પહેલેથી જ નોંધવામાં આવી નથી. નોંધ: બટન પર ક્લિક કરવાથી પેજનો ઓરિજિન GitHub પર મોકલવામાં આવશે.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { - "message": "Filter lists are updated daily. Be sure your issue has not already been addressed in the most recent filter lists.", + "message": "ફિલ્ટર યાદીઓ દૈનિક અપડેટ થાય છે. ખાતરી કરો કે તમારી સમસ્યા સૌથી તાજેતરની ફિલ્ટર યાદીઓમાં પહેલેથી જ સંબોધિત કરવામાં આવી નથી.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S2": { - "message": "Verify that the issue still exists after reloading the problematic web page.", + "message": "સમસ્યારૂપ વેબ પેજ ફરીથી લોડ કર્યા પછી સમસ્યા હજુ પણ અસ્તિત્વમાં છે તે ચકાસો.", "description": "A paragraph in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "વેબ પેજનું સરનામું:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "વેબ પેજ…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- એક એન્ટ્રી પસંદ કરો --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "જાહેરાતો અથવા જાહેરાત અવશેષો દર્શાવે છે", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "ઓવરલે અથવા અન્ય ઉપદ્રવો ધરાવે છે", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBlock Origin", + "message": "uBlock Origin શોધી કાઢે છે", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "ગોપનીયતા-સંબંધિત સમસ્યાઓ ધરાવે છે", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBlock Origin is enabled", + "message": "uBlock Origin સક્ષમ હોય ત્યારે ખામીઓ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "અનિચ્છનીય ટૅબ્સ અથવા વિન્ડોઝ ખોલે છે", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "બેડવેર, ફિશિંગ તરફ દોરી જાય છે", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "વેબ પેજને “NSFW” તરીકે લેબલ કરો (“Not Safe For Work”)", "description": "A checkbox to use for NSFW sites" }, "aboutPrivacyPolicy": { - "message": "Privacy policy", + "message": "ગોપનીયતા નીતિ", "description": "Link to privacy policy on GitHub (English)" }, "aboutChangelog": { - "message": "Changelog", + "message": "ફેરફાર યાદી", "description": "" }, "aboutCode": { - "message": "Source code (GPLv3)", + "message": "સોર્સ કોડ (GPLv3)", "description": "English: Source code (GPLv3)" }, "aboutContributors": { - "message": "Contributors", + "message": "યોગદાનકર્તાઓ", "description": "English: Contributors" }, "aboutSourceCode": { - "message": "Source code", + "message": "સોર્સ કોડ", "description": "Link text to source code repo" }, "aboutTranslations": { - "message": "Translations", + "message": "અનુવાદો", "description": "Link text to translations repo" }, "aboutFilterLists": { - "message": "Filter lists", + "message": "ફિલ્ટર યાદીઓ", "description": "Link text to uBO's own filter lists repo" }, "aboutDependencies": { - "message": "External dependencies (GPLv3-compatible):", + "message": "બાહ્ય આધારો (GPLv3-સુસંગત):", "description": "Shown in the About pane" }, "aboutCDNs": { - "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "message": "uBO ની પોતાની ફિલ્ટર યાદીઓ નીચેના CDN પર મફતમાં હોસ્ટ કરવામાં આવી છે:", "description": "Shown in the About pane" }, "aboutCDNsInfo": { - "message": "A randomly picked CDN is used when a filter list needs to be updated.", + "message": "જ્યારે ફિલ્ટર યાદી અપડેટ કરવાની જરૂર હોય ત્યારે રેન્ડમલી પસંદ કરેલ CDN નો ઉપયોગ કરવામાં આવે છે.", "description": "Shown in the About pane" }, "aboutBackupDataButton": { - "message": "Back up to file…", + "message": "ફાઇલમાં બેકઅપ લો…", "description": "Text for button to create a backup of all settings" }, "aboutBackupFilename": { @@ -1064,147 +1064,147 @@ "description": "English: my-ublock-backup_{{datetime}}.txt" }, "aboutRestoreDataButton": { - "message": "Restore from file…", + "message": "ફાઇલમાંથી પુનઃસ્થાપિત કરો…", "description": "English: Restore from file..." }, "aboutResetDataButton": { - "message": "Reset to default settings…", + "message": "મૂળભૂત સેટિંગ્સમાં રીસેટ કરો…", "description": "English: Reset to default settings..." }, "aboutRestoreDataConfirm": { - "message": "All your settings will be overwritten using data backed up on {{time}}, and uBlock₀ will restart.\n\nOverwrite all existing settings using backed up data?", + "message": "તમારી તમામ સેટિંગ્સ {{time}} પર બેકઅપ લીધેલા ડેટાનો ઉપયોગ કરીને ઓવરરાઇટ કરવામાં આવશે, અને uBlock₀ ફરીથી શરૂ થશે.\n\nબેકઅપ લીધેલા ડેટાનો ઉપયોગ કરીને તમામ હાલની સેટિંગ્સ ઓવરરાઇટ કરવી?", "description": "Message asking user to confirm restore" }, "aboutRestoreDataError": { - "message": "The data could not be read or is invalid", + "message": "ડેટા વાંચી શકાયો નહીં અથવા અમાન્ય છે", "description": "Message to display when an error occurred during restore" }, "aboutResetDataConfirm": { - "message": "All your settings will be removed, and uBlock₀ will restart.\n\nReset uBlock₀ to factory settings?", + "message": "તમારી તમામ સેટિંગ્સ દૂર કરવામાં આવશે, અને uBlock₀ ફરીથી શરૂ થશે.\n\nuBlock₀ ને ફેક્ટરી સેટિંગ્સમાં રીસેટ કરવું?", "description": "Message asking user to confirm reset" }, "errorCantConnectTo": { - "message": "Network error: {{msg}}", + "message": "નેટવર્ક ભૂલ: {{msg}}", "description": "English: Network error: {{msg}}" }, "subscribeButton": { - "message": "Subscribe", + "message": "સબ્સ્ક્રાઇબ કરો", "description": "For the button used to subscribe to a filter list" }, "elapsedOneMinuteAgo": { - "message": "a minute ago", + "message": "એક મિનિટ પહેલા", "description": "English: a minute ago" }, "elapsedManyMinutesAgo": { - "message": "{{value}} minutes ago", + "message": "{{value}} મિનિટ પહેલા", "description": "English: {{value}} minutes ago" }, "elapsedOneHourAgo": { - "message": "an hour ago", + "message": "એક કલાક પહેલા", "description": "English: an hour ago" }, "elapsedManyHoursAgo": { - "message": "{{value}} hours ago", + "message": "{{value}} કલાક પહેલા", "description": "English: {{value}} hours ago" }, "elapsedOneDayAgo": { - "message": "a day ago", + "message": "એક દિવસ પહેલા", "description": "English: a day ago" }, "elapsedManyDaysAgo": { - "message": "{{value}} days ago", + "message": "{{value}} દિવસ પહેલા", "description": "English: {{value}} days ago" }, "showDashboardButton": { - "message": "Show Dashboard", + "message": "ડેશબોર્ડ બતાવો", "description": "Firefox/Fennec-specific: Show Dashboard" }, "showNetworkLogButton": { - "message": "Show Logger", + "message": "લોગર બતાવો", "description": "Firefox/Fennec-specific: Show Logger" }, "fennecMenuItemBlockingOff": { - "message": "off", + "message": "બંધ", "description": "Firefox-specific: appears as 'uBlock₀ (off)'" }, "docblockedTitle": { - "message": "Page blocked", + "message": "પેજ અવરોધિત", "description": "Used as a title for the document-blocked page" }, "docblockedPrompt1": { - "message": "uBlock Origin has prevented the following page from loading:", + "message": "uBlock Origin એ નીચેના પેજને લોડ થતા અટકાવ્યું છે:", "description": "Used in the strict-blocking page" }, "docblockedPrompt2": { - "message": "This happened because of the following filter:", + "message": "આ નીચેના ફિલ્ટરને કારણે થયું છે:", "description": "Used in the strict-blocking page" }, "docblockedNoParamsPrompt": { - "message": "without parameters", + "message": "પરિમાણો વિના", "description": "label to be used for the parameter-less URL: https://cloud.githubusercontent.com/assets/585534/9832014/bfb1b8f0-593b-11e5-8a27-fba472a5529a.png" }, "docblockedFoundIn": { - "message": "The filter has been found in:", + "message": "ફિલ્ટર આમાં મળી આવ્યું છે:", "description": "English: List of filter list names follows" }, "docblockedBack": { - "message": "Go back", + "message": "પાછા જાઓ", "description": "English: Go back" }, "docblockedClose": { - "message": "Close this window", + "message": "આ વિન્ડો બંધ કરો", "description": "English: Close this window" }, "docblockedDontWarn": { - "message": "Don't warn me again about this site", + "message": "મને આ સાઇટ વિશે ફરીથી ચેતવણી આપશો નહીં", "description": "Label for checkbox in document-blocked page" }, "docblockedProceed": { - "message": "Disable strict blocking for {{hostname}}", + "message": "{{hostname}} માટે કડક અવરોધ અક્ષમ કરો", "description": "English: Disable strict blocking for {{hostname}} ..." }, "docblockedDisableTemporary": { - "message": "Temporarily", + "message": "કામચલાઉ", "description": "English: Temporarily" }, "docblockedDisablePermanent": { - "message": "Permanently", + "message": "કાયમી", "description": "English: Permanently" }, "docblockedDisable": { - "message": "Proceed", + "message": "આગળ વધો", "description": "Button text to navigate to the blocked page" }, "docblockedRedirectPrompt": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "અવરોધિત પેજ બીજી સાઇટ પર રીડાયરેક્ટ કરવા માંગે છે. જો તમે આગળ વધવાનું પસંદ કરો છો, તો તમે સીધા અહીં નેવિગેટ કરશો: {{url}}", "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { - "message": "Reason:", + "message": "કારણ:", "description": "The label which prepend the actual reason why a page was blocked" }, "docblockedReasonMalicious": { - "message": "Malicious", + "message": "દૂષિત", "description": "An actual reason why a page was blocked" }, "docblockedReasonTracker": { - "message": "Tracker", + "message": "ટ્રૅકર", "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { - "message": "Disreputable", + "message": "બદનામ", "description": "An actual reason why a page was blocked" }, "cloudPush": { - "message": "Export to cloud storage", + "message": "ક્લાઉડ સ્ટોરેજમાં નિકાસ કરો", "description": "tooltip" }, "cloudPull": { - "message": "Import from cloud storage", + "message": "ક્લાઉડ સ્ટોરેજમાંથી આયાત કરો", "description": "tooltip" }, "cloudPullAndMerge": { - "message": "Import from cloud storage and merge with current settings", + "message": "ક્લાઉડ સ્ટોરેજમાંથી આયાત કરો અને વર્તમાન સેટિંગ્સ સાથે મર્જ કરો", "description": "tooltip" }, "cloudNoData": { @@ -1212,75 +1212,75 @@ "description": "" }, "cloudDeviceNamePrompt": { - "message": "This device name:", + "message": "આ ઉપકરણનું નામ:", "description": "used as a prompt for the user to provide a custom device name" }, "advancedSettingsWarning": { - "message": "Warning! Change these advanced settings at your own risk.", + "message": "ચેતવણી! આ અદ્યતન સેટિંગ્સ તમારા પોતાના જોખમે બદલો.", "description": "A warning to users at the top of 'Advanced settings' page" }, "genericSubmit": { - "message": "Submit", + "message": "સબમિટ કરો", "description": "for generic 'Submit' buttons" }, "genericApplyChanges": { - "message": "Apply changes", + "message": "ફેરફારો લાગુ કરો", "description": "for generic 'Apply changes' buttons" }, "genericRevert": { - "message": "Revert", + "message": "પૂર્વવત્ કરો", "description": "for generic 'Revert' buttons" }, "genericBytes": { - "message": "bytes", + "message": "બાઇટ્સ", "description": "" }, "contextMenuBlockElementInFrame": { - "message": "Block element in frame…", + "message": "ફ્રેમમાં તત્વ અવરોધિત કરો…", "description": "An entry in the browser's contextual menu" }, "contextMenuSubscribeToList": { - "message": "Subscribe to filter list…", + "message": "ફિલ્ટર યાદીમાં સબ્સ્ક્રાઇબ કરો…", "description": "An entry in the browser's contextual menu" }, "contextMenuTemporarilyAllowLargeMediaElements": { - "message": "Temporarily allow large media elements", + "message": "મોટા મીડિયા તત્વોને કામચલાઉ મંજૂરી આપો", "description": "A context menu entry, present when large media elements have been blocked on the current site" }, "contextMenuViewSource": { - "message": "View source code…", + "message": "સોર્સ કોડ જુઓ…", "description": "A context menu entry, to view the source code of the target resource" }, "shortcutCapturePlaceholder": { - "message": "Type a shortcut", + "message": "શૉર્ટકટ ટાઇપ કરો", "description": "Placeholder string for input field used to capture a keyboard shortcut" }, "genericMergeViewScrollLock": { - "message": "Toggle locked scrolling", + "message": "લૉક કરેલ સ્ક્રોલિંગ ટૉગલ કરો", "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" }, "genericCopyToClipboard": { - "message": "Copy to clipboard", + "message": "ક્લિપબોર્ડ પર કૉપિ કરો", "description": "Label for buttons used to copy something to the clipboard" }, "genericSelectAll": { - "message": "Select all", + "message": "બધા પસંદ કરો", "description": "Label for buttons used to select all text in editor" }, "toggleCosmeticFiltering": { - "message": "Toggle cosmetic filtering", + "message": "કોસ્મેટિક ફિલ્ટરિંગ ટૉગલ કરો", "description": "Label for keyboard shortcut used to toggle cosmetic filtering" }, "toggleJavascript": { - "message": "Toggle JavaScript", + "message": "JavaScript ટૉગલ કરો", "description": "Label for keyboard shortcut used to toggle no-scripting switch" }, "relaxBlockingMode": { - "message": "Relax blocking mode", + "message": "અવરોધ મોડને હળવો કરો", "description": "Label for keyboard shortcut used to relax blocking mode" }, "storageUsed": { - "message": "Storage used: {{value}} {{unit}}", + "message": "ઉપયોગમાં લીધેલ સ્ટોરેજ: {{value}} {{unit}}", "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" }, "KB": { @@ -1296,15 +1296,15 @@ "description": "short for 'gigabytes'" }, "clickToLoad": { - "message": "Click to load", + "message": "લોડ કરવા ક્લિક કરો", "description": "Message used in frame placeholders" }, "linterMainReport": { - "message": "Errors: {{count}}", + "message": "ભૂલો: {{count}}", "description": "Summary of number of errors as reported by the linter " }, "unprocessedRequestTooltip": { - "message": "Could not filter properly at browser launch. Reload the page to ensure proper filtering.", + "message": "બ્રાઉઝર લૉન્ચ સમયે યોગ્ય રીતે ફિલ્ટર કરી શક્યા નહીં. યોગ્ય ફિલ્ટરિંગની ખાતરી કરવા પેજ ફરીથી લોડ કરો.", "description": "A warning which will appear in the popup panel if needed" }, "dummy": { diff --git a/src/_locales/he/messages.json b/src/_locales/he/messages.json index 1c137a612e31d..970a0ff4e5293 100644 --- a/src/_locales/he/messages.json +++ b/src/_locales/he/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "חוקים לוקאליים: עמודה זו היא עבור חוקים אשר תקפים לאתר הנוכחי בלבד.\nחוקים לוקאליים דורסים את החוקים הגלובליים.", + "message": "חוקים לוקאליים: עמודה זו היא עבור חוקים אשר תקפים לאתר הנוכחי בלבד.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { diff --git a/src/_locales/hi/messages.json b/src/_locales/hi/messages.json index afa3ae626029f..76e7caaba57ec 100644 --- a/src/_locales/hi/messages.json +++ b/src/_locales/hi/messages.json @@ -480,7 +480,7 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "मैलवेयर डोमेन", + "message": "मैलवेयर सुरक्षा, सिक्योरिटी", "description": "Filter lists section name" }, "3pGroupSocial": { diff --git a/src/_locales/hr/messages.json b/src/_locales/hr/messages.json index d5101bf82b0c3..d6561f1204bfe 100644 --- a/src/_locales/hr/messages.json +++ b/src/_locales/hr/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Lokalna pravila: ovaj stupac je za pravila koja vrijede samo za trenutnu stranicu.\nLokalna pravila nadjačavaju globalna pravila.", + "message": "Lokalna pravila: ovaj stupac je za pravila koja vrijede samo za trenutnu stranicu.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { diff --git a/src/_locales/hu/messages.json b/src/_locales/hu/messages.json index 26301de6d8fd5..6b71a86ce8cfc 100644 --- a/src/_locales/hu/messages.json +++ b/src/_locales/hu/messages.json @@ -4,7 +4,7 @@ "description": "extension name." }, "extShortDesc": { - "message": "Végre egy hatékony reklám- és követésblokkoló böngészőkhöz, amely kíméletes a processzorral és a memóriával.", + "message": "Végre egy hatékony blokkoló, amely kíméletes a processzorral és a memóriával.", "description": "this will be in the Chrome web store: must be 132 characters or less" }, "dashboardName": { @@ -148,7 +148,7 @@ "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoLargeMedia1": { - "message": "Kattints a nagyméretű médiaelemek blokkolásához ezen a webhelyen", + "message": "Kattintson a nagy méretű médiaelemek blokkolásához ezen a webhelyen", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoLargeMedia2": { @@ -192,7 +192,7 @@ "description": "Caption for the no-popups per-site switch" }, "popupNoLargeMedia_v2": { - "message": "Nagy média elemek", + "message": "Nagy médiaelemek", "description": "Caption for the no-large-media per-site switch" }, "popupNoCosmeticFiltering_v2": { @@ -380,7 +380,7 @@ "description": "" }, "settingsNoLargeMediaPrompt": { - "message": "Média elemek blokkolása, amelyek nagyobbak, mint {{input:number}} kB", + "message": "{{input}} kB-nál nagyobb médiaelemek blokkolása", "description": "" }, "settingsNoRemoteFontsPrompt": { @@ -960,7 +960,7 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "Az önkéntesek terhelésének csökkentése érdekében győződjön meg róla, hogy a hiba még nem lett bejelentve.", + "message": "Az önkéntesek terhelésének csökkentése érdekében győződjön meg róla, hogy a hiba még nem lett jelentve. Megjegyzés: a gombra kattintás azt okozza, hogy a lap eredete el lesz küldve a GitHub részére.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { @@ -1272,7 +1272,7 @@ "description": "Label for keyboard shortcut used to toggle cosmetic filtering" }, "toggleJavascript": { - "message": "Javascript be/ki", + "message": "JavaScript be/ki", "description": "Label for keyboard shortcut used to toggle no-scripting switch" }, "relaxBlockingMode": { diff --git a/src/_locales/hy/messages.json b/src/_locales/hy/messages.json index 9e1c212d75d0a..552935f6ee43b 100644 --- a/src/_locales/hy/messages.json +++ b/src/_locales/hy/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Տեղական կանոններ. այս սյունակը նախատեսված է միայն այս կայքի վրա տարածվող կանոնների համար։\nՏեղական կանոնները վերասահմանում են համընդհանուր կանոնները։", + "message": "Տեղական կանոններ. այս սյունակը նախատեսված է միայն այս կայքի վրա տարածվող կանոնների համար։", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -480,7 +480,7 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "Վնասակար տիրույթներ", + "message": "Վնասակար ծրագրերից պաշտպանություն, անվտանգություն", "description": "Filter lists section name" }, "3pGroupSocial": { @@ -900,11 +900,11 @@ "description": "Text for button which open an external web page in Support pane" }, "supportReportSpecificButton": { - "message": "Նոր զեկույց ստեղծել", + "message": "Նոր զեկույց ստեղծել GitHub-ում", "description": "Text for button which open an external web page in Support pane" }, "supportFindSpecificButton": { - "message": "Գտնել նման զեկույցներ", + "message": "Գտնել նման զեկույցներ GitHub-ում", "description": "A clickable link in the filter issue reporter section" }, "supportS1H": { @@ -1008,7 +1008,7 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "Բերում է վնասակար ծրագրերի, ֆիշինգի", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { @@ -1180,19 +1180,19 @@ "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { - "message": "Reason:", + "message": "Պատճառը՝", "description": "The label which prepend the actual reason why a page was blocked" }, "docblockedReasonMalicious": { - "message": "Malicious", + "message": "Վնասակար", "description": "An actual reason why a page was blocked" }, "docblockedReasonTracker": { - "message": "Tracker", + "message": "Հետևող", "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { - "message": "Disreputable", + "message": "Անվստահելի", "description": "An actual reason why a page was blocked" }, "cloudPush": { diff --git a/src/_locales/id/messages.json b/src/_locales/id/messages.json index ef6d9659b3474..00312f702437e 100644 --- a/src/_locales/id/messages.json +++ b/src/_locales/id/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Aturan lokal: kolom ini untuk aturan yang diterapkan ke situs yang sedang dikunjungi saja.\nAturan lokal menimpa aturan global.", + "message": "Aturan lokal: kolom ini untuk aturan yang diterapkan ke situs yang sedang dikunjungi saja.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -312,7 +312,7 @@ "description": "English: Click, Ctrl-click" }, "pickerContextMenuEntry": { - "message": "Blokir elemen...", + "message": "Blok elemen", "description": "An entry in the browser's contextual menu" }, "settingsCollapseBlockedPrompt": { @@ -508,7 +508,7 @@ "description": "Filter lists section name" }, "3pImport": { - "message": "Impor...", + "message": "Impor…", "description": "The label for the checkbox used to import external filter lists" }, "3pExternalListsHint": { @@ -528,7 +528,7 @@ "description": "used as a tooltip for the clock icon beside a list" }, "3pUpdating": { - "message": "Memperbarui...", + "message": "Memperbarui…", "description": "used as a tooltip for the spinner icon beside a list" }, "3pNetworkError": { @@ -592,7 +592,7 @@ "description": "Will discard manually-edited content and exit manual-edit mode" }, "rulesImport": { - "message": "Impor dari berkas...", + "message": "Impor dari berkas…", "description": "" }, "rulesExport": { @@ -1064,11 +1064,11 @@ "description": "English: my-ublock-backup_{{datetime}}.txt" }, "aboutRestoreDataButton": { - "message": "Pulihkan dari berkas...", + "message": "Pulihkan dari berkas…", "description": "English: Restore from file..." }, "aboutResetDataButton": { - "message": "Kembalikan ke pengaturan bawaan...", + "message": "Kembalikan ke pengaturan bawaan…", "description": "English: Reset to default settings..." }, "aboutRestoreDataConfirm": { @@ -1240,7 +1240,7 @@ "description": "An entry in the browser's contextual menu" }, "contextMenuSubscribeToList": { - "message": "Berlangganan daftar filter...", + "message": "Berlangganan daftar filter…", "description": "An entry in the browser's contextual menu" }, "contextMenuTemporarilyAllowLargeMediaElements": { diff --git a/src/_locales/it/messages.json b/src/_locales/it/messages.json index e5c14c07155f2..343dada288788 100644 --- a/src/_locales/it/messages.json +++ b/src/_locales/it/messages.json @@ -76,7 +76,7 @@ "description": "Message to be read by screen readers" }, "popupPowerSwitchInfo2": { - "message": "Clicca per abilitare uBlock₀ per questo sito.", + "message": "Fai clic per attivare uBlock₀ per questo sito.", "description": "Message to be read by screen readers" }, "popupBlockedRequestPrompt": { @@ -444,7 +444,7 @@ "description": "English: Parse and enforce Adblock+ element hiding filters." }, "3pParseAllABPHideFiltersInfo": { - "message": "\nI filtri cosmetici servono a nascondere gli elementi in una pagina web che sono considerati visivamente fastidiosi e che non possono essere bloccati dai motori di filtraggio basati sulle richieste di rete.", + "message": "I filtri cosmetici servono a nascondere elementi in una pagina web che sono considerati visivamente fastidiosi e che non possono essere bloccati dai motori di filtraggio basati sulle richieste di rete.", "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." }, "3pIgnoreGenericCosmeticFilters": { @@ -536,7 +536,7 @@ "description": "used as a tooltip for error icon beside a list" }, "1pTrustWarning": { - "message": "Non aggiungere filtri da fonti non affidabili.", + "message": "Non aggiungere filtri da fonti non attendibili.", "description": "Warning against copy-pasting filters from random sources" }, "1pEnableMyFiltersLabel": { @@ -960,7 +960,7 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "Per evitare di appesantire i volontari con segnalazioni doppie, verifica che il problema non sia già stato segnalato.", + "message": "Per evitare di gravare sui volontari con segnalazioni duplicate, verifica che il problema non sia già stato segnalato. Nota: cliccando il pulsante l'origine della pagina sarà inviata a GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { @@ -1176,7 +1176,7 @@ "description": "Button text to navigate to the blocked page" }, "docblockedRedirectPrompt": { - "message": "La pagina bloccata vuole reindirizzare a un altro sito. Se scegli di procedere, navigherai direttamente a: {{url}}", + "message": "La pagina bloccata tenta di reindirizzare a un altro sito. Se scegli di procedere, navigherai direttamente verso: {{url}}", "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { @@ -1304,7 +1304,7 @@ "description": "Summary of number of errors as reported by the linter " }, "unprocessedRequestTooltip": { - "message": "Non è stato effettuato correttamente il filtraggio all'avvio del browser.\nRicarica la pagina per garantire un filtraggio adeguato.", + "message": "Non è stato effettuato correttamente il filtraggio all'avvio del browser. Ricarica la pagina per garantire un filtraggio adeguato.", "description": "A warning which will appear in the popup panel if needed" }, "dummy": { diff --git a/src/_locales/ja/messages.json b/src/_locales/ja/messages.json index 3feaa8a0e9d7c..e8fc361695497 100644 --- a/src/_locales/ja/messages.json +++ b/src/_locales/ja/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "ローカルルール: この列のルールは現在のサイトだけに適用されます。\nローカルルールはグローバルルールを上書きします。", + "message": "ローカルルール: この列にあるルールは、現在のサイトのみに適用されます。", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -960,7 +960,7 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "重複した報告によってボランティアに負担をかけないように、問題がすでに報告されていないか確認してください。", + "message": "重複した報告によってボランティアに負担をかけないように、問題がすでに報告されていないか確認してください。 注意: ボタンをクリックすると、ページのオリジンが GitHub に送信されます。", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { diff --git a/src/_locales/ka/messages.json b/src/_locales/ka/messages.json index f5ad8bfc1219f..ebd3b54cd446d 100644 --- a/src/_locales/ka/messages.json +++ b/src/_locales/ka/messages.json @@ -12,11 +12,11 @@ "description": "English: uBlock₀ — Dashboard" }, "dashboardUnsavedWarning": { - "message": "გაფრთხილება! ცვლილებები არ შენახულა", + "message": "გაფრთხილება! ცვლილებები არ შენახულა!", "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "დარჩენა", + "message": "აქვე დარჩენა", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { @@ -480,7 +480,7 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "მავნე დომენები", + "message": "მავნე პროგრამებისგან დაცვა, უსაფრთხოება", "description": "Filter lists section name" }, "3pGroupSocial": { diff --git a/src/_locales/kn/messages.json b/src/_locales/kn/messages.json index 72f80be871d55..1ce63ad099cff 100644 --- a/src/_locales/kn/messages.json +++ b/src/_locales/kn/messages.json @@ -152,7 +152,7 @@ "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoLargeMedia2": { - "message": "Click to no longer block large media elements on this site", + "message": "ಈ ಸೈಟ್ನಲ್ಲಿ ದೊಡ್ಡ ಮಾಧ್ಯಮ ಅಂಶಗಳನ್ನು ಇನ್ನು ಮುಂದೆ ನಿರ್ಬಂಧಿಸದಿರಲು ಕ್ಲಿಕ್ ಮಾಡಿ", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoCosmeticFiltering": { @@ -172,11 +172,11 @@ "description": "Tooltip for the no-remote-fonts per-site switch" }, "popupTipNoRemoteFonts1": { - "message": "Click to block remote fonts on this site", + "message": "ಈ ಸೈಟ್ನಲ್ಲಿ ದೂರಸ್ಥ ಫಾಂಟ್ಗಳನ್ನು ನಿರ್ಬಂಧಿಸಲು ಕ್ಲಿಕ್ ಮಾಡಿ", "description": "Tooltip for the no-remote-fonts per-site switch" }, "popupTipNoRemoteFonts2": { - "message": "Click to no longer block remote fonts on this site", + "message": "ಈ ಸೈಟ್ನಲ್ಲಿ ದೂರಸ್ಥ ಫಾಂಟ್ಗಳನ್ನು ಇನ್ನು ಮುಂದೆ ನಿರ್ಬಂಧಿಸದಿರಲು ಕ್ಲಿಕ್ ಮಾಡಿ", "description": "Tooltip for the no-remote-fonts per-site switch" }, "popupTipNoScripting1": { @@ -184,7 +184,7 @@ "description": "Tooltip for the no-scripting per-site switch" }, "popupTipNoScripting2": { - "message": "Click to no longer disable JavaScript on this site", + "message": "ಈ ಸೈಟ್ನಲ್ಲಿ ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ ಅನ್ನು ಇನ್ನು ಮುಂದೆ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸದಿರಲು ಕ್ಲಿಕ್ ಮಾಡಿ", "description": "Tooltip for the no-scripting per-site switch" }, "popupNoPopups_v2": { @@ -200,7 +200,7 @@ "description": "Caption for the no-cosmetic-filtering per-site switch" }, "popupNoRemoteFonts_v2": { - "message": "Remote fonts", + "message": "ದೂರಸ್ಥ ಫಾಂಟ್ಗಳು", "description": "Caption for the no-remote-fonts per-site switch" }, "popupNoScripting_v2": { @@ -216,11 +216,11 @@ "description": "Label to be used to hide popup panel sections" }, "popupTipGlobalRules": { - "message": "Global rules: this column is for rules which apply to all sites.", + "message": "ಜಾಗತಿಕ ನಿಯಮಗಳು: ಈ ಕಾಲಮ್ ಎಲ್ಲಾ ಸೈಟ್ಗಳಿಗೆ ಅನ್ವಯಿಸುವ ನಿಯಮಗಳಿಗಾಗಿ.", "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Local rules: this column is for rules which apply to the current site only.", + "message": "ಸ್ಥಳೀಯ ನಿಯಮಗಳು: ಈ ಕಾಲಮ್ ಪ್ರಸ್ತುತ ಸೈಟ್ಗೆ ಮಾತ್ರ ಅನ್ವಯಿಸುವ ನಿಯಮಗಳಿಗಾಗಿ.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -320,15 +320,15 @@ "description": "English: Hide placeholders of blocked elements" }, "settingsIconBadgePrompt": { - "message": "Show the number of blocked requests on the icon", + "message": "ಐಕಾನ್ನಲ್ಲಿ ನಿರ್ಬಂಧಿಸಿದ ವಿನಂತಿಗಳ ಸಂಖ್ಯೆಯನ್ನು ತೋರಿಸು", "description": "English: Show the number of blocked requests on the icon" }, "settingsTooltipsPrompt": { - "message": "Disable tooltips", + "message": "ಸಲಹೆ ಸಂದೇಶಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸು", "description": "A checkbox in the Settings pane" }, "settingsContextMenuPrompt": { - "message": "Make use of context menu where appropriate", + "message": "ಸೂಕ್ತವಾದಲ್ಲಿ ಸಂದರ್ಭ ಮೆನುವನ್ನು ಬಳಸು", "description": "English: Make use of context menu where appropriate" }, "settingsColorBlindPrompt": { @@ -344,11 +344,11 @@ "description": "Label for checkbox to enable a custom dark theme" }, "settingsThemeAccent0Label": { - "message": "Custom accent color", + "message": "ಕಸ್ಟಮ್ ಆಕ್ಸೆಂಟ್ ಬಣ್ಣ", "description": "Label for checkbox to pick an accent color" }, "settingsCloudStorageEnabledPrompt": { - "message": "Enable cloud storage support", + "message": "ಕ್ಲೌಡ್ ಸಂಗ್ರಹಣೆ ಬೆಂಬಲವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸು", "description": "" }, "settingsAdvancedUserPrompt": { @@ -356,35 +356,35 @@ "description": "Checkbox to let user access advanced, technical features" }, "settingsPrefetchingDisabledPrompt": { - "message": "Disable pre-fetching (to prevent any connection for blocked network requests)", + "message": "ಪೂರ್ವ-ಎಚ್ಚರಿಕೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸು (ನಿರ್ಬಂಧಿಸಿದ ಜಾಲ ವಿನಂತಿಗಳಿಗೆ ಯಾವುದೇ ಸಂಪರ್ಕವನ್ನು ತಡೆಯಲು)", "description": "English: " }, "settingsHyperlinkAuditingDisabledPrompt": { - "message": "Disable hyperlink auditing", + "message": "ಹೈಪರ್ಲಿಂಕ್ ಪರಿಶೀಲನೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸು", "description": "English: " }, "settingsWebRTCIPAddressHiddenPrompt": { - "message": "Prevent WebRTC from leaking local IP addresses", + "message": "ಸ್ಥಳೀಯ IP ವಿಳಾಸಗಳನ್ನು ಸೋರಿಕೆಯಾಗದಂತೆ WebRTC ಅನ್ನು ತಡೆ", "description": "English: " }, "settingPerSiteSwitchGroup": { - "message": "Default behavior", + "message": "ಡೀಫಾಲ್ಟ್ ವರ್ತನೆ", "description": "" }, "settingPerSiteSwitchGroupSynopsis": { - "message": "These default behaviors can be overridden on a per-site basis", + "message": "ಈ ಡೀಫಾಲ್ಟ್ ವರ್ತನೆಗಳನ್ನು ಪ್ರತಿ-ಸೈಟ್ ಆಧಾರದ ಮೇಲೆ ಅತಿಕ್ರಮಿಸಬಹುದು", "description": "" }, "settingsNoCosmeticFilteringPrompt": { - "message": "Disable cosmetic filtering", + "message": "ಸೌಂದರ್ಯ ಶೋಧನೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸು", "description": "" }, "settingsNoLargeMediaPrompt": { - "message": "Block media elements larger than {{input}} KB", + "message": "{{input}} KB ಗಿಂತ ದೊಡ್ಡದಾದ ಮಾಧ್ಯಮ ಅಂಶಗಳನ್ನು ನಿರ್ಬಂಧಿಸು", "description": "" }, "settingsNoRemoteFontsPrompt": { - "message": "Block remote fonts", + "message": "ದೂರಸ್ಥ ಫಾಂಟ್ಗಳನ್ನು ನಿರ್ಬಂಧಿಸು", "description": "" }, "settingsNoScriptingPrompt": { @@ -392,11 +392,11 @@ "description": "The default state for the per-site no-scripting switch" }, "settingsNoCSPReportsPrompt": { - "message": "Block CSP reports", + "message": "CSP ವರದಿಗಳನ್ನು ನಿರ್ಬಂಧಿಸು", "description": "background information: https://github.com/gorhill/uBlock/issues/3150" }, "settingsUncloakCnamePrompt": { - "message": "Uncloak canonical names", + "message": "ಅಂಗೀಕೃತ ಹೆಸರುಗಳನ್ನು ಅನಾವರಣಗೊಳಿಸು", "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" }, "settingsAdvanced": { @@ -404,7 +404,7 @@ "description": "Section for controlling advanced-user settings" }, "settingsAdvancedSynopsis": { - "message": "Features suitable only for technical users", + "message": "ತಾಂತ್ರಿಕ ಬಳಕೆದಾರರಿಗೆ ಮಾತ್ರ ಸೂಕ್ತವಾದ ವೈಶಿಷ್ಟ್ಯಗಳು", "description": "Description of section controlling advanced-user settings" }, "settingsAdvancedUserSettings": { @@ -412,7 +412,7 @@ "description": "For the tooltip of a link which gives access to advanced settings" }, "settingsLastRestorePrompt": { - "message": "Last restore:", + "message": "ಕೊನೆಯ ಮರುಸ್ಥಾಪನೆ:", "description": "English: Last restore:" }, "settingsLastBackupPrompt": { @@ -436,27 +436,27 @@ "description": "A button in the in the _3rd-party filters_ pane" }, "3pPurgeAll": { - "message": "Purge all caches", + "message": "ಎಲ್ಲಾ ಸಂಗ್ರಹಗಳನ್ನು ಖಾಲಿಮಾಡು", "description": "A button in the in the _3rd-party filters_ pane" }, "3pParseAllABPHideFiltersPrompt1": { - "message": "Parse and enforce cosmetic filters", + "message": "ಸೌಂದರ್ಯ ಶೋಧಕಗಳನ್ನು ವಿಶ್ಲೇಷಿಸಿ ಮತ್ತು ಜಾರಿಗೊಳಿಸು", "description": "English: Parse and enforce Adblock+ element hiding filters." }, "3pParseAllABPHideFiltersInfo": { - "message": "Cosmetic filters serve to hide elements in a web page which are deemed to be a visual nuisance, and which can't be blocked by the network request-based filtering engines.", + "message": "ಸೌಂದರ್ಯ ಶೋಧಕಗಳು ವೆಬ್ ಪುಟದಲ್ಲಿ ದೃಶ್ಯ ತೊಂದರೆಯೆಂದು ಪರಿಗಣಿಸಲಾದ ಮತ್ತು ಜಾಲ ವಿನಂತಿ-ಆಧಾರಿತ ಶೋಧನಾ ಎಂಜಿನ್ಗಳಿಂದ ನಿರ್ಬಂಧಿಸಲಾಗದ ಅಂಶಗಳನ್ನು ಮರೆಮಾಡಲು ಸಹಾಯ ಮಾಡುತ್ತವೆ.", "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." }, "3pIgnoreGenericCosmeticFilters": { - "message": "Ignore generic cosmetic filters", + "message": "ಸಾಮಾನ್ಯ ಸೌಂದರ್ಯ ಶೋಧಕಗಳನ್ನು ನಿರ್ಲಕ್ಷಿಸು", "description": "This will cause uBO to ignore all generic cosmetic filters." }, "3pIgnoreGenericCosmeticFiltersInfo": { - "message": "Generic cosmetic filters are those cosmetic filters which are meant to apply on all web sites. Enabling this option will eliminate the memory and CPU overhead added to web pages as a result of handling generic cosmetic filters.\n\nIt is recommended to enable this option on less powerful devices.", + "message": "ಸಾಮಾನ್ಯ ಸೌಂದರ್ಯ ಶೋಧಕಗಳು ಎಂದರೆ ಎಲ್ಲಾ ವೆಬ್ ಸೈಟ್ಗಳಿಗೆ ಅನ್ವಯಿಸಲು ಉದ್ದೇಶಿಸಲಾದ ಆ ಸೌಂದರ್ಯ ಶೋಧಕಗಳು. ಈ ಆಯ್ಕೆಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುವುದರಿಂದ ಸಾಮಾನ್ಯ ಸೌಂದರ್ಯ ಶೋಧಕಗಳನ್ನು ನಿರ್ವಹಿಸುವ ಪರಿಣಾಮವಾಗಿ ವೆಬ್ ಪುಟಗಳಿಗೆ ಸೇರುವ ಮೆಮೊರಿ ಮತ್ತು CPU ಹೊರೆಯನ್ನು ನಿವಾರಿಸುತ್ತದೆ.\n\nಕಡಿಮೆ ಶಕ್ತಿಯುತ ಸಾಧನಗಳಲ್ಲಿ ಈ ಆಯ್ಕೆಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು ಶಿಫಾರಸು ಮಾಡಲಾಗಿದೆ.", "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." }, "3pSuspendUntilListsAreLoaded": { - "message": "Suspend network activity until all filter lists are loaded", + "message": "ಎಲ್ಲಾ ಶೋಧಕ ಪಟ್ಟಿಗಳು ಲೋಡ್ ಆಗುವವರೆಗೆ ಜಾಲ ಚಟುವಟಿಕೆಯನ್ನು ಅಮಾನತುಗೊಳಿಸು", "description": "A checkbox in the 'Filter lists' pane" }, "3pListsOfBlockedHostsHeader": { @@ -468,7 +468,7 @@ "description": "English: Apply changes" }, "3pGroupDefault": { - "message": "Built-in", + "message": "ಅಂತರ್ನಿರ್ಮಿತ", "description": "Filter lists section name" }, "3pGroupAds": { @@ -484,15 +484,15 @@ "description": "Filter lists section name" }, "3pGroupSocial": { - "message": "Social widgets", + "message": "ಸಾಮಾಜಿಕ ವಿಜೆಟ್ಗಳು", "description": "Filter lists section name" }, "3pGroupCookies": { - "message": "Cookie notices", + "message": "ಕುಕೀ ಸೂಚನೆಗಳು", "description": "Filter lists section name" }, "3pGroupAnnoyances": { - "message": "Annoyances", + "message": "ಕಿರಿಕಿರಿಗಳು", "description": "Filter lists section name" }, "3pGroupMultipurpose": { @@ -512,7 +512,7 @@ "description": "The label for the checkbox used to import external filter lists" }, "3pExternalListsHint": { - "message": "One URL per line. Invalid URLs will be silently ignored.", + "message": "ಪ್ರತಿ ಸಾಲಿಗೆ ಒಂದು URL. ಅಮಾನ್ಯ URLಗಳನ್ನು ಮೌನವಾಗಿ ನಿರ್ಲಕ್ಷಿಸಲಾಗುವುದು.", "description": "Short information about how to use the textarea to import external filter lists by URL" }, "3pExternalListObsolete": { @@ -524,7 +524,7 @@ "description": "used as a tooltip for eye icon beside a list" }, "3pLastUpdate": { - "message": "Last update: {{ago}}.\nClick to force an update.", + "message": "ಕೊನೆಯ ನವೀಕರಣ: {{ago}}.\nಒತ್ತಾಯಪೂರ್ವಕ ನವೀಕರಣಕ್ಕಾಗಿ ಕ್ಲಿಕ್ ಮಾಡಿ.", "description": "used as a tooltip for the clock icon beside a list" }, "3pUpdating": { @@ -532,19 +532,19 @@ "description": "used as a tooltip for the spinner icon beside a list" }, "3pNetworkError": { - "message": "A network error prevented the resource from being updated.", + "message": "ಜಾಲ ದೋಷವು ಸಂಪನ್ಮೂಲವನ್ನು ನವೀಕರಿಸದಂತೆ ತಡೆಯಿತು.", "description": "used as a tooltip for error icon beside a list" }, "1pTrustWarning": { - "message": "Do not add filters from untrusted sources.", + "message": "ಅವಿಶ್ವಾಸಾರ್ಹ ಮೂಲಗಳಿಂದ ಶೋಧಕಗಳನ್ನು ಸೇರಿಸಬೇಡಿ.", "description": "Warning against copy-pasting filters from random sources" }, "1pEnableMyFiltersLabel": { - "message": "Enable my custom filters", + "message": "ನನ್ನ ಕಸ್ಟಮ್ ಶೋಧಕಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸು", "description": "Label for the checkbox use to enable/disable 'My filters' list" }, "1pTrustMyFiltersLabel": { - "message": "Allow custom filters requiring trust", + "message": "ವಿಶ್ವಾಸದ ಅಗತ್ಯವಿರುವ ಕಸ್ಟಮ್ ಶೋಧಕಗಳನ್ನು ಅನುಮತಿಸು", "description": "Label for the checkbox use to trust the content of 'My filters' list" }, "1pImport": { @@ -596,7 +596,7 @@ "description": "" }, "rulesExport": { - "message": "Export to file…", + "message": "ಫೈಲ್ಗೆ ರಫ್ತು ಮಾಡು…", "description": "Button in the 'My rules' pane" }, "rulesDefaultFileName": { @@ -604,15 +604,15 @@ "description": "default file name to use" }, "rulesHint": { - "message": "List of your dynamic filtering rules.", + "message": "ನಿಮ್ಮ ಕ್ರಿಯಾತ್ಮಕ ಶೋಧನಾ ನಿಯಮಗಳ ಪಟ್ಟಿ.", "description": "English: List of your dynamic filtering rules." }, "rulesFormatHint": { - "message": "Rule syntax: source destination type action (full documentation).", + "message": "ನಿಯಮ ಸಿಂಟ್ಯಾಕ್ಸ್: ಮೂಲ ಗಮ್ಯಸ್ಥಾನ ಪ್ರಕಾರ ಕ್ರಿಯೆ (ಪೂರ್ಣ ದಸ್ತಾವೇಜು).", "description": "English: dynamic rule syntax and full documentation." }, "rulesSort": { - "message": "Sort:", + "message": "ವಿಂಗಡಿಸು:", "description": "English: label for sort option." }, "rulesSortByType": { @@ -628,7 +628,7 @@ "description": "English: a sort option for list of rules." }, "whitelistPrompt": { - "message": "The trusted site directives dictate on which web pages uBlock Origin should be disabled. One entry per line.", + "message": "ವಿಶ್ವಾಸಾರ್ಹ ಸೈಟ್ ನಿರ್ದೇಶನಗಳು ಯಾವ ವೆಬ್ ಪುಟಗಳಲ್ಲಿ uBlock Origin ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಬೇಕೆಂದು ಸೂಚಿಸುತ್ತವೆ. ಪ್ರತಿ ಸಾಲಿಗೆ ಒಂದು ನಮೂದು.", "description": "A concise description of the 'Trusted sites' pane." }, "whitelistImport": { @@ -668,7 +668,7 @@ "description": "Appears in the logger's tab selector" }, "logBehindTheScene": { - "message": "Tabless", + "message": "ಟ್ಯಾಬ್ ಇಲ್ಲದ", "description": "Pretty name for behind-the-scene network requests" }, "loggerCurrentTab": { @@ -676,43 +676,43 @@ "description": "Appears in the logger's tab selector" }, "loggerReloadTip": { - "message": "Reload the tab content", + "message": "ಟ್ಯಾಬ್ ವಿಷಯವನ್ನು ಮರುಲೋಡ್ ಮಾಡು", "description": "Tooltip for the reload button in the logger page" }, "loggerDomInspectorTip": { - "message": "Toggle the DOM inspector", + "message": "DOM ತಪಾಸಣೆಗಾರನನ್ನು ಟಾಗಲ್ ಮಾಡು", "description": "Tooltip for the DOM inspector button in the logger page" }, "loggerPopupPanelTip": { - "message": "Toggle the popup panel", + "message": "ಪಾಪಪ್ ಫಲಕವನ್ನು ಟಾಗಲ್ ಮಾಡು", "description": "Tooltip for the popup panel button in the logger page" }, "loggerInfoTip": { - "message": "uBlock Origin wiki: The logger", + "message": "uBlock Origin ವಿಕಿ: ದ ಲಾಗರ್", "description": "Tooltip for the top-right info label in the logger page" }, "loggerClearTip": { - "message": "Clear logger", + "message": "ಲಾಗರ್ ಅನ್ನು ತೆರವುಗೊಳಿಸು", "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" }, "loggerPauseTip": { - "message": "Pause logger (discard all incoming data)", + "message": "ಲಾಗರ್ ಅನ್ನು ವಿರಾಮಗೊಳಿಸು (ಎಲ್ಲಾ ಆಗಮಿಸುವ ದತ್ತಾಂಶವನ್ನು ತ್ಯಜಿಸು)", "description": "Tooltip for the pause button in the logger page" }, "loggerUnpauseTip": { - "message": "Unpause logger", + "message": "ಲಾಗರ್ ಅನ್ನು ವಿರಾಮರಹಿತಗೊಳಿಸು", "description": "Tooltip for the play button in the logger page" }, "loggerRowFiltererButtonTip": { - "message": "Toggle logger filtering", + "message": "ಲಾಗರ್ ಶೋಧನೆಯನ್ನು ಟಾಗಲ್ ಮಾಡು", "description": "Tooltip for the row filterer button in the logger page" }, "logFilterPrompt": { - "message": "filter logger content", + "message": "ಲಾಗರ್ ವಿಷಯವನ್ನು ಶೋಧಿಸು", "description": "Placeholder string for logger output filtering input field" }, "loggerRowFiltererBuiltinTip": { - "message": "Logger filtering options", + "message": "ಲಾಗರ್ ಶೋಧನಾ ಆಯ್ಕೆಗಳು", "description": "Tooltip for the button to bring up logger output filtering options" }, "loggerRowFiltererBuiltinNot": { @@ -724,7 +724,7 @@ "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" }, "loggerRowFiltererBuiltinBlocked": { - "message": "blocked", + "message": "ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ", "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltinAllowed": { @@ -732,15 +732,15 @@ "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltinModified": { - "message": "modified", + "message": "ಮಾರ್ಪಡಿಸಲಾಗಿದೆ", "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltin1p": { - "message": "1st-party", + "message": "1ನೇ-ಪಕ್ಷ", "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltin3p": { - "message": "3rd-party", + "message": "3ನೇ-ಪಕ್ಷ", "description": "A keyword in the built-in row filtering expression" }, "loggerEntryDetailsHeader": { @@ -760,15 +760,15 @@ "description": "Label to identify a rule field" }, "loggerEntryDetailsContext": { - "message": "Context", + "message": "ಸಂದರ್ಭ", "description": "Label to identify a context field (typically a hostname)" }, "loggerEntryDetailsRootContext": { - "message": "Root context", + "message": "ಮೂಲ ಸಂದರ್ಭ", "description": "Label to identify a root context field (typically a hostname)" }, "loggerEntryDetailsPartyness": { - "message": "Partyness", + "message": "ಪಕ್ಷತೆ", "description": "Label to identify a field providing partyness information" }, "loggerEntryDetailsType": { @@ -784,7 +784,7 @@ "description": "Small header to identify the dynamic URL filtering section" }, "loggerURLFilteringContextLabel": { - "message": "Context:", + "message": "ಸಂದರ್ಭ:", "description": "Label for the context selector" }, "loggerURLFilteringTypeLabel": { @@ -792,11 +792,11 @@ "description": "Label for the type selector" }, "loggerStaticFilteringHeader": { - "message": "Static filter", + "message": "ಸ್ಥಿರ ಶೋಧಕ", "description": "Small header to identify the static filtering section" }, "loggerStaticFilteringSentence": { - "message": "{{action}} network requests of {{type}} {{br}}which URL address matches {{url}} {{br}}and which originates {{origin}},{{br}}{{importance}} there is a matching exception filter.", + "message": "{{action}} {{type}} ನ ಜಾಲ ವಿನಂತಿಗಳು {{br}}ಇದರ URL ವಿಳಾಸವು {{url}} ಗೆ ಹೊಂದಿಕೆಯಾಗುತ್ತದೆ {{br}}ಮತ್ತು ಇದು {{origin}} ನಿಂದ ಉದ್ಭವಿಸುತ್ತದೆ,{{br}}{{importance}} ಹೊಂದಾಣಿಕೆಯ ಅಪವಾದ ಶೋಧಕವಿದೆ.", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartBlock": { @@ -808,11 +808,11 @@ "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartType": { - "message": "type “{{type}}”", + "message": "“{{type}}” ಪ್ರಕಾರ", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartAnyType": { - "message": "any type", + "message": "ಯಾವುದೇ ಪ್ರಕಾರ", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartOrigin": { @@ -820,47 +820,47 @@ "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartAnyOrigin": { - "message": "from anywhere", + "message": "ಎಲ್ಲಿಂದಲಾದರೂ", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartNotImportant": { - "message": "except when", + "message": "ಹೊರತುಪಡಿಸಿ", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartImportant": { - "message": "even if", + "message": "ಆದರೂ ಸಹ", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringFinderSentence1": { - "message": "Static filter {{filter}} found in:", + "message": "ಸ್ಥಿರ ಶೋಧಕ {{filter}} ಇಲ್ಲಿ ಕಂಡುಬಂದಿದೆ:", "description": "Below this sentence, the filter list(s) in which the filter was found" }, "loggerStaticFilteringFinderSentence2": { - "message": "Static filter could not be found in any of the currently enabled filter lists", + "message": "ಸ್ಥಿರ ಶೋಧಕವು ಪ್ರಸ್ತುತ ಸಕ್ರಿಯಗೊಳಿಸಲಾದ ಯಾವುದೇ ಶೋಧಕ ಪಟ್ಟಿಗಳಲ್ಲಿ ಕಂಡುಬಂದಿಲ್ಲ", "description": "Message to show when a filter cannot be found in any filter lists" }, "loggerSettingDiscardPrompt": { - "message": "Logger entries which do not fulfill all three conditions below will be automatically discarded:", + "message": "ಕೆಳಗಿನ ಎಲ್ಲಾ ಮೂರು ಷರತ್ತುಗಳನ್ನು ಪೂರೈಸದ ಲಾಗರ್ ನಮೂದುಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ತ್ಯಜಿಸಲಾಗುವುದು:", "description": "Logger setting: A sentence to describe the purpose of the settings below" }, "loggerSettingPerEntryMaxAge": { - "message": "Preserve entries from the last {{input}} minutes", + "message": "ಕೊನೆಯ {{input}} ನಿಮಿಷಗಳಿಂದ ನಮೂದುಗಳನ್ನು ಸಂರಕ್ಷಿಸು", "description": "A logger setting" }, "loggerSettingPerTabMaxLoads": { - "message": "Preserve at most {{input}} page loads per tab", + "message": "ಪ್ರತಿ ಟ್ಯಾಬ್ಗೆ ಗರಿಷ್ಠ {{input}} ಪುಟ ಲೋಡ್ಗಳನ್ನು ಸಂರಕ್ಷಿಸು", "description": "A logger setting" }, "loggerSettingPerTabMaxEntries": { - "message": "Preserve at most {{input}} entries per tab", + "message": "ಪ್ರತಿ ಟ್ಯಾಬ್ಗೆ ಗರಿಷ್ಠ {{input}} ನಮೂದುಗಳನ್ನು ಸಂರಕ್ಷಿಸು", "description": "A logger setting" }, "loggerSettingPerEntryLineCount": { - "message": "Use {{input}} lines per entry in vertically expanded mode", + "message": "ಲಂಬವಾಗಿ ವಿಸ್ತರಿಸಿದ ಮೋಡ್ನಲ್ಲಿ ಪ್ರತಿ ನಮೂದಿಗೆ {{input}} ಸಾಲುಗಳನ್ನು ಬಳಸು", "description": "A logger setting" }, "loggerSettingHideColumnsPrompt": { - "message": "Hide columns:", + "message": "ಕಾಲಮ್ಗಳನ್ನು ಮರೆಮಾಡು:", "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" }, "loggerSettingHideColumnTime": { @@ -868,23 +868,23 @@ "description": "A label for the time column" }, "loggerSettingHideColumnFilter": { - "message": "{{input}} Filter/rule", + "message": "{{input}} ಶೋಧಕ/ನಿಯಮ", "description": "A label for the filter or rule column" }, "loggerSettingHideColumnContext": { - "message": "{{input}} Context", + "message": "{{input}} ಸಂದರ್ಭ", "description": "A label for the context column" }, "loggerSettingHideColumnPartyness": { - "message": "{{input}} Partyness", + "message": "{{input}} ಪಕ್ಷತೆ", "description": "A label for the partyness column" }, "loggerExportFormatList": { - "message": "List", + "message": "ಪಟ್ಟಿ", "description": "Label for radio-button to pick export format" }, "loggerExportFormatTable": { - "message": "Table", + "message": "ಕೋಷ್ಟಕ", "description": "Label for radio-button to pick export format" }, "loggerExportEncodePlain": { @@ -892,7 +892,7 @@ "description": "Label for radio-button to pick export text format" }, "loggerExportEncodeMarkdown": { - "message": "Markdown", + "message": "ಮಾರ್ಕ್ಡೌನ್", "description": "Label for radio-button to pick export text format" }, "supportOpenButton": { @@ -900,119 +900,119 @@ "description": "Text for button which open an external web page in Support pane" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "GitHub ನಲ್ಲಿ ಹೊಸ ವರದಿಯನ್ನು ರಚಿಸು", "description": "Text for button which open an external web page in Support pane" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "GitHub ನಲ್ಲಿ ಹೋಲುವ ವರದಿಗಳನ್ನು ಹುಡುಕು", "description": "A clickable link in the filter issue reporter section" }, "supportS1H": { - "message": "Documentation", + "message": "ದಸ್ತಾವೇಜು", "description": "Header of 'Documentation' section in Support pane" }, "supportS1P1": { - "message": "Read the documentation at uBlock/wiki to learn about all of uBlock Origin's features.", + "message": "uBlock Origin ನ ಎಲ್ಲಾ ವೈಶಿಷ್ಟ್ಯಗಳ ಬಗ್ಗೆ ತಿಳಿಯಲು uBlock/wiki ನಲ್ಲಿ ದಸ್ತಾವೇಜನ್ನು ಓದಿ.", "description": "First paragraph of 'Documentation' section in Support pane" }, "supportS2H": { - "message": "Questions and support", + "message": "ಪ್ರಶ್ನೆಗಳು ಮತ್ತು ಬೆಂಬಲ", "description": "Header of 'Questions and support' section in Support pane" }, "supportS2P1": { - "message": "Answers to questions and other kinds of help support is provided on the subreddit /r/uBlockOrigin.", + "message": "ಪ್ರಶ್ನೆಗಳಿಗೆ ಉತ್ತರಗಳು ಮತ್ತು ಇತರ ರೀತಿಯ ಸಹಾಯ ಬೆಂಬಲವನ್ನು /r/uBlockOrigin ಉಪರೆಡ್ಡಿಟ್ನಲ್ಲಿ ಒದಗಿಸಲಾಗಿದೆ.", "description": "First paragraph of 'Questions and support' section in Support pane" }, "supportS3H": { - "message": "Filter issues/website is broken", + "message": "ಶೋಧಕ ಸಮಸ್ಯೆಗಳು/ವೆಬ್ಸೈಟ್ ಮುರಿದುಹೋಗಿದೆ", "description": "Header of 'Filter issues' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "ನಿರ್ದಿಷ್ಟ ವೆಬ್ಸೈಟ್ಗಳೊಂದಿಗಿನ ಶೋಧಕ ಸಮಸ್ಯೆಗಳನ್ನು uBlockOrigin/uAssets ಸಮಸ್ಯೆ ಟ್ರ್ಯಾಕರ್ಗೆ ವರದಿ ಮಾಡಿ. GitHub ಖಾತೆಯ ಅಗತ್ಯವಿದೆ.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS3P2": { - "message": "Important: Avoid using other similarly-purposed blockers along with uBlock Origin, as this may cause filter issues on specific websites.", + "message": "ಮುಖ್ಯ: uBlock Origin ಜೊತೆಗೆ ಇತರ ರೀತಿಯ ಉದ್ದೇಶದ ನಿರ್ಬಂಧಕಗಳನ್ನು ಬಳಸುವುದನ್ನು ತಪ್ಪಿಸಿ, ಏಕೆಂದರೆ ಇದು ನಿರ್ದಿಷ್ಟ ವೆಬ್ಸೈಟ್ಗಳಲ್ಲಿ ಶೋಧಕ ಸಮಸ್ಯೆಗಳಿಗೆ ಕಾರಣವಾಗಬಹುದು.", "description": "Second paragraph of 'Filter issues' section in Support pane" }, "supportS3P3": { - "message": "Tips: Be sure your filter lists are up to date. The logger is the primary tool to diagnose filter-related issues.", + "message": "ಸಲಹೆಗಳು: ನಿಮ್ಮ ಶೋಧಕ ಪಟ್ಟಿಗಳು ನವೀಕೃತವಾಗಿವೆಯೆಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ. ಶೋಧಕ-ಸಂಬಂಧಿತ ಸಮಸ್ಯೆಗಳನ್ನು ಪತ್ತೆಹಚ್ಚಲು ಲಾಗರ್ ಪ್ರಾಥಮಿಕ ಸಾಧನವಾಗಿದೆ.", "description": "Third paragraph of 'Filter issues' section in Support pane" }, "supportS4H": { - "message": "Bug report", + "message": "ದೋಷ ವರದಿ", "description": "Header of 'Bug report' section in Support pane" }, "supportS4P1": { - "message": "Report issues with uBlock Origin itself to the uBlockOrigin/uBlock-issue issue tracker. Requires a GitHub account.", + "message": "uBlock Origin ನಲ್ಲಿನ ಸಮಸ್ಯೆಗಳನ್ನು uBlockOrigin/uBlock-issue ಸಮಸ್ಯೆ ಟ್ರ್ಯಾಕರ್ಗೆ ವರದಿ ಮಾಡಿ. GitHub ಖಾತೆಯ ಅಗತ್ಯವಿದೆ.", "description": "First paragraph of 'Bug report' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting Information", + "message": "ಸಮಸ್ಯೆ ನಿವಾರಣೆ ಮಾಹಿತಿ", "description": "Header of 'Troubleshooting Information' section in Support pane" }, "supportS5P1": { - "message": "Below is technical information that might be useful when volunteers are trying to help you solve a problem.", + "message": "ಸ್ವಯಂಸೇವಕರು ನಿಮ್ಮ ಸಮಸ್ಯೆಯನ್ನು ಪರಿಹರಿಸಲು ಪ್ರಯತ್ನಿಸುವಾಗ ಉಪಯುಕ್ತವಾಗಬಹುದಾದ ತಾಂತ್ರಿಕ ಮಾಹಿತಿಯನ್ನು ಕೆಳಗೆ ನೀಡಲಾಗಿದೆ.", "description": "First paragraph of 'Troubleshooting Information' section in Support pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "ಶೋಧಕ ಸಮಸ್ಯೆಯನ್ನು ವರದಿ ಮಾಡಿ", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "ಸ್ವಯಂಸೇವಕರಿಗೆ ನಕಲು ವರದಿಗಳ ಹೊರೆಯನ್ನು ತಪ್ಪಿಸಲು, ಸಮಸ್ಯೆಯನ್ನು ಈಗಾಗಲೇ ವರದಿ ಮಾಡಿಲ್ಲವೆಂದು ದಯವಿಟ್ಟು ಪರಿಶೀಲಿಸಿ. ಸೂಚನೆ: ಬಟನ್ ಕ್ಲಿಕ್ ಮಾಡುವುದರಿಂದ ಪುಟದ ಮೂಲವನ್ನು GitHub ಗೆ ಕಳುಹಿಸಲಾಗುತ್ತದೆ.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { - "message": "Filter lists are updated daily. Be sure your issue has not already been addressed in the most recent filter lists.", + "message": "ಶೋಧಕ ಪಟ್ಟಿಗಳನ್ನು ಪ್ರತಿದಿನ ನವೀಕರಿಸಲಾಗುತ್ತದೆ. ನಿಮ್ಮ ಸಮಸ್ಯೆಯನ್ನು ಇತ್ತೀಚಿನ ಶೋಧಕ ಪಟ್ಟಿಗಳಲ್ಲಿ ಈಗಾಗಲೇ ಪರಿಹರಿಸಿಲ್ಲವೆಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S2": { - "message": "Verify that the issue still exists after reloading the problematic web page.", + "message": "ಸಮಸ್ಯಾತ್ಮಕ ವೆಬ್ ಪುಟವನ್ನು ಮರುಲೋಡ್ ಮಾಡಿದ ನಂತರ ಸಮಸ್ಯೆ ಇನ್ನೂ ಅಸ್ತಿತ್ವದಲ್ಲಿದೆಯೆಂದು ಪರಿಶೀಲಿಸಿ.", "description": "A paragraph in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "ವೆಬ್ ಪುಟದ ವಿಳಾಸ:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "ವೆಬ್ ಪುಟ…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- ಒಂದು ನಮೂದನ್ನು ಆಯ್ಕೆಮಾಡಿ --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "ಜಾಹೀರಾತುಗಳು ಅಥವಾ ಜಾಹೀರಾತು ಉಳಿಕೆಗಳನ್ನು ತೋರಿಸುತ್ತದೆ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "ಓವರ್ಲೇಗಳು ಅಥವಾ ಇತರ ತೊಂದರೆಗಳನ್ನು ಹೊಂದಿದೆ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBlock Origin", + "message": "uBlock Origin ಅನ್ನು ಪತ್ತೆ ಮಾಡುತ್ತದೆ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "ಗೌಪ್ಯತೆ-ಸಂಬಂಧಿತ ಸಮಸ್ಯೆಗಳನ್ನು ಹೊಂದಿದೆ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBlock Origin is enabled", + "message": "uBlock Origin ಸಕ್ರಿಯವಾಗಿರುವಾಗ ಅಸಮರ್ಪಕವಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "ಅನಪೇಕ್ಷಿತ ಟ್ಯಾಬ್ಗಳು ಅಥವಾ ವಿಂಡೋಗಳನ್ನು ತೆರೆಯುತ್ತದೆ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "ದುರುಪಯೋಗಿ ಸಾಫ್ಟ್ವೇರ್, ಫಿಶಿಂಗ್ಗೆ ಕಾರಣವಾಗುತ್ತದೆ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "ವೆಬ್ ಪುಟವನ್ನು “NSFW” ಎಂದು ಗುರುತಿಸು (“ಕೆಲಸಕ್ಕೆ ಸುರಕ್ಷಿತವಲ್ಲ”)", "description": "A checkbox to use for NSFW sites" }, "aboutPrivacyPolicy": { @@ -1024,7 +1024,7 @@ "description": "" }, "aboutCode": { - "message": "Source code (GPLv3)", + "message": "ಮೂಲ ಕೋಡ್ (GPLv3)", "description": "English: Source code (GPLv3)" }, "aboutContributors": { @@ -1044,19 +1044,19 @@ "description": "Link text to uBO's own filter lists repo" }, "aboutDependencies": { - "message": "External dependencies (GPLv3-compatible):", + "message": "ಬಾಹ್ಯ ಅವಲಂಬನೆಗಳು (GPLv3-ಹೊಂದಾಣಿಕೆ):", "description": "Shown in the About pane" }, "aboutCDNs": { - "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "message": "uBO ನ ಸ್ವಂತ ಶೋಧಕ ಪಟ್ಟಿಗಳನ್ನು ಈ ಕೆಳಗಿನ CDN ಗಳಲ್ಲಿ ಉಚಿತವಾಗಿ ಹೋಸ್ಟ್ ಮಾಡಲಾಗಿದೆ:", "description": "Shown in the About pane" }, "aboutCDNsInfo": { - "message": "A randomly picked CDN is used when a filter list needs to be updated.", + "message": "ಶೋಧಕ ಪಟ್ಟಿಯನ್ನು ನವೀಕರಿಸಬೇಕಾದಾಗ ಯಾದೃಚ್ಛಿಕವಾಗಿ ಆಯ್ಕೆಮಾಡಿದ CDN ಅನ್ನು ಬಳಸಲಾಗುತ್ತದೆ.", "description": "Shown in the About pane" }, "aboutBackupDataButton": { - "message": "Back up to file…", + "message": "ಫೈಲ್ಗೆ ಬ್ಯಾಕಪ್ ಮಾಡು…", "description": "Text for button to create a backup of all settings" }, "aboutBackupFilename": { @@ -1064,27 +1064,27 @@ "description": "English: my-ublock-backup_{{datetime}}.txt" }, "aboutRestoreDataButton": { - "message": "Restore from file…", + "message": "ಫೈಲ್ನಿಂದ ಮರುಸ್ಥಾಪಿಸು…", "description": "English: Restore from file..." }, "aboutResetDataButton": { - "message": "Reset to default settings…", + "message": "ಡೀಫಾಲ್ಟ್ ಸೆಟ್ಟಿಂಗ್ಗಳಿಗೆ ಮರುಹೊಂದಿಸು…", "description": "English: Reset to default settings..." }, "aboutRestoreDataConfirm": { - "message": "All your settings will be overwritten using data backed up on {{time}}, and uBlock₀ will restart.\n\nOverwrite all existing settings using backed up data?", + "message": "ನಿಮ್ಮ ಎಲ್ಲಾ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು {{time}} ರಂದು ಬ್ಯಾಕಪ್ ಮಾಡಿದ ದತ್ತಾಂಶವನ್ನು ಬಳಸಿಕೊಂಡು ಅತಿಕ್ರಮಿಸಲಾಗುವುದು, ಮತ್ತು uBlock₀ ಮರುಪ್ರಾರಂಭವಾಗುತ್ತದೆ.\n\nಬ್ಯಾಕಪ್ ಮಾಡಿದ ದತ್ತಾಂಶವನ್ನು ಬಳಸಿಕೊಂಡು ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಎಲ್ಲಾ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಅತಿಕ್ರಮಿಸುವುದೇ?", "description": "Message asking user to confirm restore" }, "aboutRestoreDataError": { - "message": "The data could not be read or is invalid", + "message": "ದತ್ತಾಂಶವನ್ನು ಓದಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ ಅಥವಾ ಅಮಾನ್ಯವಾಗಿದೆ", "description": "Message to display when an error occurred during restore" }, "aboutResetDataConfirm": { - "message": "All your settings will be removed, and uBlock₀ will restart.\n\nReset uBlock₀ to factory settings?", + "message": "ನಿಮ್ಮ ಎಲ್ಲಾ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ತೆಗೆದುಹಾಕಲಾಗುವುದು, ಮತ್ತು uBlock₀ ಮರುಪ್ರಾರಂಭವಾಗುತ್ತದೆ.\n\nuBlock₀ ಅನ್ನು ಕಾರ್ಖಾನೆ ಸೆಟ್ಟಿಂಗ್ಗಳಿಗೆ ಮರುಹೊಂದಿಸುವುದೇ?", "description": "Message asking user to confirm reset" }, "errorCantConnectTo": { - "message": "Network error: {{msg}}", + "message": "ಜಾಲ ದೋಷ: {{msg}}", "description": "English: Network error: {{msg}}" }, "subscribeButton": { @@ -1116,11 +1116,11 @@ "description": "English: {{value}} days ago" }, "showDashboardButton": { - "message": "Show Dashboard", + "message": "ಡ್ಯಾಶ್ಬೋರ್ಡ್ ತೋರಿಸು", "description": "Firefox/Fennec-specific: Show Dashboard" }, "showNetworkLogButton": { - "message": "Show Logger", + "message": "ಲಾಗರ್ ತೋರಿಸು", "description": "Firefox/Fennec-specific: Show Logger" }, "fennecMenuItemBlockingOff": { @@ -1128,7 +1128,7 @@ "description": "Firefox-specific: appears as 'uBlock₀ (off)'" }, "docblockedTitle": { - "message": "Page blocked", + "message": "ಪುಟ ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ", "description": "Used as a title for the document-blocked page" }, "docblockedPrompt1": { @@ -1136,15 +1136,15 @@ "description": "Used in the strict-blocking page" }, "docblockedPrompt2": { - "message": "This happened because of the following filter:", + "message": "ಈ ಕೆಳಗಿನ ಶೋಧಕದಿಂದಾಗಿ ಇದು ಸಂಭವಿಸಿದೆ:", "description": "Used in the strict-blocking page" }, "docblockedNoParamsPrompt": { - "message": "without parameters", + "message": "ನಿಯತಾಂಕಗಳಿಲ್ಲದೆ", "description": "label to be used for the parameter-less URL: https://cloud.githubusercontent.com/assets/585534/9832014/bfb1b8f0-593b-11e5-8a27-fba472a5529a.png" }, "docblockedFoundIn": { - "message": "The filter has been found in:", + "message": "ಶೋಧಕವು ಇಲ್ಲಿ ಕಂಡುಬಂದಿದೆ:", "description": "English: List of filter list names follows" }, "docblockedBack": { @@ -1156,11 +1156,11 @@ "description": "English: Close this window" }, "docblockedDontWarn": { - "message": "Don't warn me again about this site", + "message": "ಈ ಸೈಟ್ ಬಗ್ಗೆ ಮತ್ತೆ ಎಚ್ಚರಿಸಬೇಡಿ", "description": "Label for checkbox in document-blocked page" }, "docblockedProceed": { - "message": "Disable strict blocking for {{hostname}}", + "message": "{{hostname}} ಗಾಗಿ ಕಟ್ಟುನಿಟ್ಟಿನ ನಿರ್ಬಂಧವನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸು", "description": "English: Disable strict blocking for {{hostname}} ..." }, "docblockedDisableTemporary": { @@ -1172,39 +1172,39 @@ "description": "English: Permanently" }, "docblockedDisable": { - "message": "Proceed", + "message": "ಮುಂದುವರಿಯಿರಿ", "description": "Button text to navigate to the blocked page" }, "docblockedRedirectPrompt": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "ನಿರ್ಬಂಧಿಸಿದ ಪುಟವು ಇನ್ನೊಂದು ಸೈಟ್ಗೆ ಮರುನಿರ್ದೇಶಿಸಲು ಬಯಸುತ್ತದೆ. ನೀವು ಮುಂದುವರಿಯಲು ಆರಿಸಿದರೆ, ನೀವು ನೇರವಾಗಿ ಇಲ್ಲಿಗೆ ನ್ಯಾವಿಗೇಟ್ ಮಾಡುತ್ತೀರಿ: {{url}}", "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { - "message": "Reason:", + "message": "ಕಾರಣ:", "description": "The label which prepend the actual reason why a page was blocked" }, "docblockedReasonMalicious": { - "message": "Malicious", + "message": "ದುರುದ್ದೇಶಪೂರಿತ", "description": "An actual reason why a page was blocked" }, "docblockedReasonTracker": { - "message": "Tracker", + "message": "ಟ್ರ್ಯಾಕರ್", "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { - "message": "Disreputable", + "message": "ಅಪ್ರತಿಷ್ಠಿತ", "description": "An actual reason why a page was blocked" }, "cloudPush": { - "message": "Export to cloud storage", + "message": "ಕ್ಲೌಡ್ ಸಂಗ್ರಹಣೆಗೆ ರಫ್ತು ಮಾಡು", "description": "tooltip" }, "cloudPull": { - "message": "Import from cloud storage", + "message": "ಕ್ಲೌಡ್ ಸಂಗ್ರಹಣೆಯಿಂದ ಆಮದು ಮಾಡು", "description": "tooltip" }, "cloudPullAndMerge": { - "message": "Import from cloud storage and merge with current settings", + "message": "ಕ್ಲೌಡ್ ಸಂಗ್ರಹಣೆಯಿಂದ ಆಮದು ಮಾಡಿ ಮತ್ತು ಪ್ರಸ್ತುತ ಸೆಟ್ಟಿಂಗ್ಗಳೊಂದಿಗೆ ವಿಲೀನಗೊಳಿಸು", "description": "tooltip" }, "cloudNoData": { @@ -1216,7 +1216,7 @@ "description": "used as a prompt for the user to provide a custom device name" }, "advancedSettingsWarning": { - "message": "Warning! Change these advanced settings at your own risk.", + "message": "ಎಚ್ಚರಿಕೆ! ಈ ಸುಧಾರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ನಿಮ್ಮ ಸ್ವಂತ ಜವಾಬ್ದಾರಿಯಲ್ಲಿ ಬದಲಾಯಿಸಿ.", "description": "A warning to users at the top of 'Advanced settings' page" }, "genericSubmit": { @@ -1236,47 +1236,47 @@ "description": "" }, "contextMenuBlockElementInFrame": { - "message": "Block element in frame…", + "message": "ಫ್ರೇಮ್ನಲ್ಲಿ ಅಂಶವನ್ನು ನಿರ್ಬಂಧಿಸು…", "description": "An entry in the browser's contextual menu" }, "contextMenuSubscribeToList": { - "message": "Subscribe to filter list…", + "message": "ಶೋಧಕ ಪಟ್ಟಿಗೆ ಚಂದಾದಾರರಾಗು…", "description": "An entry in the browser's contextual menu" }, "contextMenuTemporarilyAllowLargeMediaElements": { - "message": "Temporarily allow large media elements", + "message": "ದೊಡ್ಡ ಮಾಧ್ಯಮ ಅಂಶಗಳನ್ನು ತಾತ್ಕಾಲಿಕವಾಗಿ ಅನುಮತಿಸು", "description": "A context menu entry, present when large media elements have been blocked on the current site" }, "contextMenuViewSource": { - "message": "View source code…", + "message": "ಮೂಲ ಕೋಡ್ ವೀಕ್ಷಿಸು…", "description": "A context menu entry, to view the source code of the target resource" }, "shortcutCapturePlaceholder": { - "message": "Type a shortcut", + "message": "ಶಾರ್ಟ್ಕಟ್ ಅನ್ನು ಟೈಪ್ ಮಾಡಿ", "description": "Placeholder string for input field used to capture a keyboard shortcut" }, "genericMergeViewScrollLock": { - "message": "Toggle locked scrolling", + "message": "ಲಾಕ್ ಮಾಡಿದ ಸ್ಕ್ರೋಲಿಂಗ್ ಅನ್ನು ಟಾಗಲ್ ಮಾಡು", "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" }, "genericCopyToClipboard": { - "message": "Copy to clipboard", + "message": "ಕ್ಲಿಪ್ಬೋರ್ಡ್ಗೆ ನಕಲಿಸು", "description": "Label for buttons used to copy something to the clipboard" }, "genericSelectAll": { - "message": "Select all", + "message": "ಎಲ್ಲವನ್ನೂ ಆಯ್ಕೆಮಾಡು", "description": "Label for buttons used to select all text in editor" }, "toggleCosmeticFiltering": { - "message": "Toggle cosmetic filtering", + "message": "ಸೌಂದರ್ಯ ಶೋಧನೆಯನ್ನು ಟಾಗಲ್ ಮಾಡು", "description": "Label for keyboard shortcut used to toggle cosmetic filtering" }, "toggleJavascript": { - "message": "Toggle JavaScript", + "message": "ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ ಅನ್ನು ಟಾಗಲ್ ಮಾಡು", "description": "Label for keyboard shortcut used to toggle no-scripting switch" }, "relaxBlockingMode": { - "message": "Relax blocking mode", + "message": "ನಿರ್ಬಂಧಿಸುವ ಮೋಡ್ ಅನ್ನು ಸಡಿಲಗೊಳಿಸು", "description": "Label for keyboard shortcut used to relax blocking mode" }, "storageUsed": { @@ -1296,15 +1296,15 @@ "description": "short for 'gigabytes'" }, "clickToLoad": { - "message": "Click to load", + "message": "ಲೋಡ್ ಮಾಡಲು ಕ್ಲಿಕ್ ಮಾಡಿ", "description": "Message used in frame placeholders" }, "linterMainReport": { - "message": "Errors: {{count}}", + "message": "ದೋಷಗಳು: {{count}}", "description": "Summary of number of errors as reported by the linter " }, "unprocessedRequestTooltip": { - "message": "Could not filter properly at browser launch. Reload the page to ensure proper filtering.", + "message": "ಬ್ರೌಸರ್ ಪ್ರಾರಂಭದಲ್ಲಿ ಸರಿಯಾಗಿ ಶೋಧಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ. ಸರಿಯಾದ ಶೋಧನೆಯನ್ನು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಲು ಪುಟವನ್ನು ಮರುಲೋಡ್ ಮಾಡಿ.", "description": "A warning which will appear in the popup panel if needed" }, "dummy": { diff --git a/src/_locales/ko/messages.json b/src/_locales/ko/messages.json index 490427875847f..83ddbd8dc9f1d 100644 --- a/src/_locales/ko/messages.json +++ b/src/_locales/ko/messages.json @@ -16,7 +16,7 @@ "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "취소", + "message": "머무르기", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { @@ -76,7 +76,7 @@ "description": "Message to be read by screen readers" }, "popupPowerSwitchInfo2": { - "message": "클릭하여 이 사이트에서 uBlock₀ 을 켭니다.", + "message": "클릭하여 이 사이트에서 uBlock₀을 켭니다.", "description": "Message to be read by screen readers" }, "popupBlockedRequestPrompt": { @@ -116,11 +116,11 @@ "description": "English: Click to open the dashboard" }, "popupTipZapper": { - "message": "구성 요소 선택기 모드로 진입", + "message": "요소 제거기 모드 진입", "description": "Tooltip for the element-zapper icon in the popup panel" }, "popupTipPicker": { - "message": "구성 요소 선택기 모드로 진입", + "message": "요소 선택기 모드 진입", "description": "English: Enter element picker mode" }, "popupTipLog": { @@ -144,15 +144,15 @@ "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoLargeMedia": { - "message": "이 사이트에서만 적용되는 대용량 미디어 요소 차단 기능을 켜고 끕니다", + "message": "이 사이트에서 적용되는 대용량 미디어 요소 차단 기능 토글", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoLargeMedia1": { - "message": "클릭하여 이 사이트에서 대용량 미디어를 차단합니다", + "message": "클릭하여 이 사이트에서 대용량 미디어 요소를 차단합니다", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoLargeMedia2": { - "message": "클릭하여 이 사이트에서 대용량 미디어 차단을 해제합니다", + "message": "클릭하여 이 사이트에서 대용량 미디어 요소 차단을 해제합니다", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoCosmeticFiltering": { @@ -312,11 +312,11 @@ "description": "English: Click, Ctrl-click" }, "pickerContextMenuEntry": { - "message": "구성 요소 차단", + "message": "요소 차단…", "description": "An entry in the browser's contextual menu" }, "settingsCollapseBlockedPrompt": { - "message": "차단된 요소의 자리 감추기", + "message": "차단된 요소의 공간 숨기기", "description": "English: Hide placeholders of blocked elements" }, "settingsIconBadgePrompt": { @@ -380,7 +380,7 @@ "description": "" }, "settingsNoLargeMediaPrompt": { - "message": "{{input:number}} KB 보다 큰 미디어 구성요소 차단", + "message": "{{input}} KB보다 큰 미디어 요소 차단", "description": "" }, "settingsNoRemoteFontsPrompt": { @@ -488,7 +488,7 @@ "description": "Filter lists section name" }, "3pGroupCookies": { - "message": "쿠키 공지", + "message": "쿠키 알림", "description": "Filter lists section name" }, "3pGroupAnnoyances": { @@ -508,7 +508,7 @@ "description": "Filter lists section name" }, "3pImport": { - "message": "불러오기..", + "message": "가져오기…", "description": "The label for the checkbox used to import external filter lists" }, "3pExternalListsHint": { @@ -528,7 +528,7 @@ "description": "used as a tooltip for the clock icon beside a list" }, "3pUpdating": { - "message": "업데이트 중...", + "message": "업데이트 중…", "description": "used as a tooltip for the spinner icon beside a list" }, "3pNetworkError": { @@ -536,7 +536,7 @@ "description": "used as a tooltip for error icon beside a list" }, "1pTrustWarning": { - "message": "신뢰할 수 없는 출처의 필터를 추가하지 마십시오.", + "message": "신뢰할 수 없는 출처의 필터는 추가하지 마세요.", "description": "Warning against copy-pasting filters from random sources" }, "1pEnableMyFiltersLabel": { @@ -592,7 +592,7 @@ "description": "Will discard manually-edited content and exit manual-edit mode" }, "rulesImport": { - "message": "파일로부터 불러오기...", + "message": "파일에서 가져오기…", "description": "" }, "rulesExport": { @@ -668,7 +668,7 @@ "description": "Appears in the logger's tab selector" }, "logBehindTheScene": { - "message": "숨겨진 구성 요소", + "message": "숨겨진 요소", "description": "Pretty name for behind-the-scene network requests" }, "loggerCurrentTab": { @@ -1204,7 +1204,7 @@ "description": "tooltip" }, "cloudPullAndMerge": { - "message": "클라우드 저장소의 설정 불러오기 및 현재 설정과 통합", + "message": "클라우드 저장소에서 가져와 현재 설정에 병합", "description": "tooltip" }, "cloudNoData": { @@ -1236,7 +1236,7 @@ "description": "" }, "contextMenuBlockElementInFrame": { - "message": "프레임 내 구성 요소 차단", + "message": "프레임 내 요소 차단…", "description": "An entry in the browser's contextual menu" }, "contextMenuSubscribeToList": { diff --git a/src/_locales/lt/messages.json b/src/_locales/lt/messages.json index 15f3a90ba263a..6d86a6a288351 100644 --- a/src/_locales/lt/messages.json +++ b/src/_locales/lt/messages.json @@ -16,7 +16,7 @@ "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "Pasilikti", + "message": "Pasilikti čia", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Vietinės taisyklės: ši skiltis skirta dabartiniam puslapiui taikomoms taisyklėms.\nVietinės taisyklės nustelbia globalias.", + "message": "Vietinės taisyklės: ši skiltis skirta dabartiniam puslapiui taikomoms taisyklėms.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -280,7 +280,7 @@ "description": "Appears as an option to filter out firewall rows" }, "popup3pFrameFilter": { - "message": "frame", + "message": "kadras", "description": "Appears as an option to filter out firewall rows" }, "pickerCreate": { @@ -344,7 +344,7 @@ "description": "Label for checkbox to enable a custom dark theme" }, "settingsThemeAccent0Label": { - "message": "Custom accent color", + "message": "Pasirinktinis akcentinė spalva", "description": "Label for checkbox to pick an accent color" }, "settingsCloudStorageEnabledPrompt": { @@ -396,7 +396,7 @@ "description": "background information: https://github.com/gorhill/uBlock/issues/3150" }, "settingsUncloakCnamePrompt": { - "message": "Uncloak canonical names", + "message": "Atskleisti kanoninius vardus", "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" }, "settingsAdvanced": { @@ -404,7 +404,7 @@ "description": "Section for controlling advanced-user settings" }, "settingsAdvancedSynopsis": { - "message": "Features suitable only for technical users", + "message": "Funkcijos, tinkamos tik techniniams vartotojams", "description": "Description of section controlling advanced-user settings" }, "settingsAdvancedUserSettings": { @@ -456,7 +456,7 @@ "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." }, "3pSuspendUntilListsAreLoaded": { - "message": "Suspend network activity until all filter lists are loaded", + "message": "Pristabdyti tinklo veiklą, kol bus įkelti visi filtrų sąrašai", "description": "A checkbox in the 'Filter lists' pane" }, "3pListsOfBlockedHostsHeader": { @@ -480,15 +480,15 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "Kenksmingos sritys", + "message": "Apsauga nuo kenkėjiškų programų, saugumas", "description": "Filter lists section name" }, "3pGroupSocial": { - "message": "Social widgets", + "message": "Socialiniai valdikliai", "description": "Filter lists section name" }, "3pGroupCookies": { - "message": "Cookie notices", + "message": "Slapukų pranešimai", "description": "Filter lists section name" }, "3pGroupAnnoyances": { @@ -536,15 +536,15 @@ "description": "used as a tooltip for error icon beside a list" }, "1pTrustWarning": { - "message": "Do not add filters from untrusted sources.", + "message": "Nepridėkite filtrų iš nepatikimų šaltinių.", "description": "Warning against copy-pasting filters from random sources" }, "1pEnableMyFiltersLabel": { - "message": "Enable my custom filters", + "message": "Įjungti mano pasirinktinius filtrus", "description": "Label for the checkbox use to enable/disable 'My filters' list" }, "1pTrustMyFiltersLabel": { - "message": "Allow custom filters requiring trust", + "message": "Leisti pasirinktinius filtrus, kuriems reikia pasitikėjimo", "description": "Label for the checkbox use to trust the content of 'My filters' list" }, "1pImport": { @@ -768,7 +768,7 @@ "description": "Label to identify a root context field (typically a hostname)" }, "loggerEntryDetailsPartyness": { - "message": "Partyness", + "message": "Šališkumas", "description": "Label to identify a field providing partyness information" }, "loggerEntryDetailsType": { @@ -848,35 +848,35 @@ "description": "A logger setting" }, "loggerSettingPerTabMaxLoads": { - "message": "Preserve at most {{input}} page loads per tab", + "message": "Išsaugoti ne daugiau kaip {{input}} puslapio įkėlimų kiekvienai kortelei", "description": "A logger setting" }, "loggerSettingPerTabMaxEntries": { - "message": "Preserve at most {{input}} entries per tab", + "message": "Išsaugoti ne daugiau kaip {{input}} įrašų kiekvienai kortelei", "description": "A logger setting" }, "loggerSettingPerEntryLineCount": { - "message": "Use {{input}} lines per entry in vertically expanded mode", + "message": "Naudoti {{input}} eilutes kiekvienam įrašui vertikaliai išplėstame režime", "description": "A logger setting" }, "loggerSettingHideColumnsPrompt": { - "message": "Hide columns:", + "message": "Slėpti stulpelius:", "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" }, "loggerSettingHideColumnTime": { - "message": "{{input}} Time", + "message": "{{input}} Laikas", "description": "A label for the time column" }, "loggerSettingHideColumnFilter": { - "message": "{{input}} Filter/rule", + "message": "{{input}} Filtras/taisyklė", "description": "A label for the filter or rule column" }, "loggerSettingHideColumnContext": { - "message": "{{input}} Context", + "message": "{{input}} Kontekstas", "description": "A label for the context column" }, "loggerSettingHideColumnPartyness": { - "message": "{{input}} Partyness", + "message": "{{input}} Šališkumas", "description": "A label for the partyness column" }, "loggerExportFormatList": { @@ -912,7 +912,7 @@ "description": "Header of 'Documentation' section in Support pane" }, "supportS1P1": { - "message": "Read the documentation at uBlock/wiki to learn about all of uBlock Origin's features.", + "message": "Skaitykite dokumentaciją adresu uBlock/wiki, kad sužinotumėte apie visas uBlock Origin funkcijas.", "description": "First paragraph of 'Documentation' section in Support pane" }, "supportS2H": { @@ -920,23 +920,23 @@ "description": "Header of 'Questions and support' section in Support pane" }, "supportS2P1": { - "message": "Answers to questions and other kinds of help support is provided on the subreddit /r/uBlockOrigin.", + "message": "Atsakymai į klausimus ir kitokia pagalba teikiama subreddit /r/uBlockOrigin.", "description": "First paragraph of 'Questions and support' section in Support pane" }, "supportS3H": { - "message": "Filter issues/website is broken", + "message": "Filtrų problemos / svetainė neveikia", "description": "Header of 'Filter issues' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "Praneškite apie filtrų problemas su konkrečiomis svetainėmis uBlockOrigin/uAssets problemų sekimo sistemoje. Reikia GitHub paskyros.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS3P2": { - "message": "Important: Avoid using other similarly-purposed blockers along with uBlock Origin, as this may cause filter issues on specific websites.", + "message": "Svarbu: Venkite naudoti kitus panašios paskirties blokuoklius kartu su uBlock Origin, nes tai gali sukelti filtrų problemų konkrečiose svetainėse.", "description": "Second paragraph of 'Filter issues' section in Support pane" }, "supportS3P3": { - "message": "Tips: Be sure your filter lists are up to date. The logger is the primary tool to diagnose filter-related issues.", + "message": "Patarimai: Įsitikinkite, kad jūsų filtrų sąrašai yra atnaujinti. Žurnalas yra pagrindinis įrankis diagnozuojant su filtrais susijusias problemas.", "description": "Third paragraph of 'Filter issues' section in Support pane" }, "supportS4H": { @@ -944,75 +944,75 @@ "description": "Header of 'Bug report' section in Support pane" }, "supportS4P1": { - "message": "Report issues with uBlock Origin itself to the uBlockOrigin/uBlock-issue issue tracker. Requires a GitHub account.", + "message": "Praneškite apie problemas su pačiu uBlock Origin uBlockOrigin/uBlock-issue problemų sekimo sistemoje. Reikia GitHub paskyros.", "description": "First paragraph of 'Bug report' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting Information", + "message": "Triktčių šalinimo informacija", "description": "Header of 'Troubleshooting Information' section in Support pane" }, "supportS5P1": { - "message": "Below is technical information that might be useful when volunteers are trying to help you solve a problem.", + "message": "Žemiau pateikiama techninė informacija, kuri gali būti naudinga, kai savanoriai bando padėti jums išspręsti problemą.", "description": "First paragraph of 'Troubleshooting Information' section in Support pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "Pranešti apie filtro problemą", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "Kad neapkrautumėte savanorių dubliavimosi pranešimais, patikrinkite, ar ši problema jau nebuvo pranešta. Pastaba: paspaudus mygtuką, puslapio kilmė bus išsiųsta į GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { - "message": "Filter lists are updated daily. Be sure your issue has not already been addressed in the most recent filter lists.", + "message": "Filtrų sąrašai atnaujinami kasdien. Įsitikinkite, kad jūsų problema jau nebuvo išspręsta naujausiuose filtrų sąrašuose.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S2": { - "message": "Verify that the issue still exists after reloading the problematic web page.", + "message": "Patikrinkite, ar problema vis dar egzistuoja po probleminio tinklalapio perkrovimo.", "description": "A paragraph in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "Tinklalapio adresas:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "Tinklalapis…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- Pasirinkite įrašą --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "Rodo skelbimus arba skelbimų likučius", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "Turi perdangas ar kitus trukdžius", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBlock Origin", + "message": "Aptinka uBlock Origin", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "Turi su privatumu susijusių problemų", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBlock Origin is enabled", + "message": "Veikia netinkamai, kai įjungtas uBlock Origin", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "Atidaro nepageidaujamas korteles ar langus", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "Veda prie kenkėjiškų programų, sukčiavimo (phishing)", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "Pažymėti tinklalapį kaip „NSFW“ („Netinkama darbui“)", "description": "A checkbox to use for NSFW sites" }, "aboutPrivacyPolicy": { @@ -1048,11 +1048,11 @@ "description": "Shown in the About pane" }, "aboutCDNs": { - "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "message": "uBO nuosavi filtrų sąrašai yra nemokamai talpinami šiuose CDN:", "description": "Shown in the About pane" }, "aboutCDNsInfo": { - "message": "A randomly picked CDN is used when a filter list needs to be updated.", + "message": "Kai reikia atnaujinti filtrų sąrašą, naudojamas atsitiktinai parinktas CDN.", "description": "Shown in the About pane" }, "aboutBackupDataButton": { @@ -1156,7 +1156,7 @@ "description": "English: Close this window" }, "docblockedDontWarn": { - "message": "Don't warn me again about this site", + "message": "Daugiau neįspėti manęs apie šią svetainę", "description": "Label for checkbox in document-blocked page" }, "docblockedProceed": { @@ -1176,23 +1176,23 @@ "description": "Button text to navigate to the blocked page" }, "docblockedRedirectPrompt": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "Užblokuotas puslapis nori nukreipti į kitą svetainę. Jei nuspręsite tęsti, būsite tiesiogiai nukreipti į: {{url}}", "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { - "message": "Reason:", + "message": "Priežastis:", "description": "The label which prepend the actual reason why a page was blocked" }, "docblockedReasonMalicious": { - "message": "Malicious", + "message": "Kenkėjiška", "description": "An actual reason why a page was blocked" }, "docblockedReasonTracker": { - "message": "Tracker", + "message": "Sekimo priemonė", "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { - "message": "Disreputable", + "message": "Abejotina", "description": "An actual reason why a page was blocked" }, "cloudPush": { @@ -1236,11 +1236,11 @@ "description": "" }, "contextMenuBlockElementInFrame": { - "message": "Block element in frame…", + "message": "Blokuoti elementą kadre…", "description": "An entry in the browser's contextual menu" }, "contextMenuSubscribeToList": { - "message": "Subscribe to filter list…", + "message": "Prenumeruoti filtrų sąrašą…", "description": "An entry in the browser's contextual menu" }, "contextMenuTemporarilyAllowLargeMediaElements": { @@ -1248,7 +1248,7 @@ "description": "A context menu entry, present when large media elements have been blocked on the current site" }, "contextMenuViewSource": { - "message": "View source code…", + "message": "Peržiūrėti šaltinio kodą…", "description": "A context menu entry, to view the source code of the target resource" }, "shortcutCapturePlaceholder": { @@ -1256,7 +1256,7 @@ "description": "Placeholder string for input field used to capture a keyboard shortcut" }, "genericMergeViewScrollLock": { - "message": "Toggle locked scrolling", + "message": "Perjungti užrakintą slinkimą", "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" }, "genericCopyToClipboard": { @@ -1268,19 +1268,19 @@ "description": "Label for buttons used to select all text in editor" }, "toggleCosmeticFiltering": { - "message": "Toggle cosmetic filtering", + "message": "Perjungti kosmetinį filtravimą", "description": "Label for keyboard shortcut used to toggle cosmetic filtering" }, "toggleJavascript": { - "message": "Toggle JavaScript", + "message": "Perjungti JavaScript", "description": "Label for keyboard shortcut used to toggle no-scripting switch" }, "relaxBlockingMode": { - "message": "Relax blocking mode", + "message": "Sumažinti blokavimo režimą", "description": "Label for keyboard shortcut used to relax blocking mode" }, "storageUsed": { - "message": "Storage used: {{value}} {{unit}}", + "message": "Naudojama atmintis: {{value}} {{unit}}", "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" }, "KB": { @@ -1296,7 +1296,7 @@ "description": "short for 'gigabytes'" }, "clickToLoad": { - "message": "Click to load", + "message": "Spustelėkite, kad įkeltumėte", "description": "Message used in frame placeholders" }, "linterMainReport": { @@ -1304,7 +1304,7 @@ "description": "Summary of number of errors as reported by the linter " }, "unprocessedRequestTooltip": { - "message": "Could not filter properly at browser launch. Reload the page to ensure proper filtering.", + "message": "Nepavyko tinkamai filtruoti paleidus naršyklę. Įkelkite puslapį iš naujo, kad užtikrintumėte tinkamą filtravimą.", "description": "A warning which will appear in the popup panel if needed" }, "dummy": { diff --git a/src/_locales/lv/messages.json b/src/_locales/lv/messages.json index c884504ae9d68..716365db27385 100644 --- a/src/_locales/lv/messages.json +++ b/src/_locales/lv/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Vietējie ierobežojumi: šī kolonna paredzēta ierobežojumiem, kas attieksies tikai uz konkrēto mājaslapu.\nVietējie ierobežojumi pārraksta globālos ierobežojumus.", + "message": "Vietējie ierobežojumi: šī kolonna paredzēta ierobežojumiem, kas attieksies tikai uz konkrēto mājaslapu.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -960,7 +960,7 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "Lai izvairītos no brīvprātīgo noslogošanas ar ziņojumiem, kas atkārtojas, lūgums pārbaudīt, vai par šādu nepilnību jau ir ziņots.", + "message": "Lai izvairītos no brīvprātīgo noslogošanas ar ziņojumiem, kas atkārtojas, lūgums pārbaudīt, ka par šādu nepilnību jau nav ziņots. Piebilde: klikšķināšana uz pogas izraisīs arī lapas izcelsmes nosūtīšanu uz GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { diff --git a/src/_locales/mk/messages.json b/src/_locales/mk/messages.json index d6981beae583c..fac31e27bfe7e 100644 --- a/src/_locales/mk/messages.json +++ b/src/_locales/mk/messages.json @@ -16,7 +16,7 @@ "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "Остани", + "message": "Остани тука", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Локални правила: оваа колона е за правила што се однесуваат само на моменталниот сајт.\nЛокални правила надминуваат глобални правила.", + "message": "Локални правила: оваа колона е за правила што се однесуваат само на моменталниот сајт.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -480,7 +480,7 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "Домени на малвер", + "message": "Заштита од малициозен софтвер, безбедност", "description": "Filter lists section name" }, "3pGroupSocial": { @@ -1180,19 +1180,19 @@ "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { - "message": "Reason:", + "message": "Причина:", "description": "The label which prepend the actual reason why a page was blocked" }, "docblockedReasonMalicious": { - "message": "Malicious", + "message": "Злонамерен", "description": "An actual reason why a page was blocked" }, "docblockedReasonTracker": { - "message": "Tracker", + "message": "Следач", "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { - "message": "Disreputable", + "message": "Со лош глас", "description": "An actual reason why a page was blocked" }, "cloudPush": { diff --git a/src/_locales/ml/messages.json b/src/_locales/ml/messages.json index 29db607005447..1d5e9a068e5cc 100644 --- a/src/_locales/ml/messages.json +++ b/src/_locales/ml/messages.json @@ -16,7 +16,7 @@ "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "താമസിക്കുക", + "message": "ഇവിടെ തുടരുക", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "പ്രാദേശിക നിയമങ്ങൾ: ഈ കോളത്തിലെ നിയമങ്ങൾ നിലവിലെ സൈറ്റിലെ മാത്രം പ്രയോഗിക്കുന്ന.\nപ്രാദേശിക നിയമങ്ങൾ ആഗോള നിയമങ്ങൾ അതിലംഘിച്ച് പ്രവർത്തിക്കുന്നതായിരിക്കും.", + "message": "പ്രാദേശിക നിയമങ്ങൾ: ഈ കോളത്തിലെ നിയമങ്ങൾ നിലവിലെ സൈറ്റിലെ മാത്രം പ്രയോഗിക്കുന്ന.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -276,11 +276,11 @@ "description": "Example of use: Version 1.26.4" }, "popup3pScriptFilter": { - "message": "script", + "message": "സ്ക്രിപ്റ്റ്", "description": "Appears as an option to filter out firewall rows" }, "popup3pFrameFilter": { - "message": "frame", + "message": "ഫ്രെയിം", "description": "Appears as an option to filter out firewall rows" }, "pickerCreate": { @@ -336,15 +336,15 @@ "description": "English: Color-blind friendly" }, "settingsAppearance": { - "message": "Appearance", + "message": "രൂപഭാവം", "description": "Section for controlling user interface appearance" }, "settingsThemeLabel": { - "message": "Theme", + "message": "തീം", "description": "Label for checkbox to enable a custom dark theme" }, "settingsThemeAccent0Label": { - "message": "Custom accent color", + "message": "ഇഷ്ടാനുസൃത ആക്സന്റ് നിറം", "description": "Label for checkbox to pick an accent color" }, "settingsCloudStorageEnabledPrompt": { @@ -404,7 +404,7 @@ "description": "Section for controlling advanced-user settings" }, "settingsAdvancedSynopsis": { - "message": "Features suitable only for technical users", + "message": "സാങ്കേതിക ഉപയോക്താക്കൾക്ക് മാത്രം അനുയോജ്യമായ സവിശേഷതകൾ", "description": "Description of section controlling advanced-user settings" }, "settingsAdvancedUserSettings": { @@ -456,7 +456,7 @@ "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." }, "3pSuspendUntilListsAreLoaded": { - "message": "Suspend network activity until all filter lists are loaded", + "message": "എല്ലാ ഫിൽറ്റർ ലിസ്റ്റുകളും ലോഡ് ആകുന്നത് വരെ നെറ്റ്വർക്ക് പ്രവർത്തനം താൽക്കാലികമായി നിർത്തുക", "description": "A checkbox in the 'Filter lists' pane" }, "3pListsOfBlockedHostsHeader": { @@ -480,15 +480,15 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "മാല്‍വെയര്‍ ഡൊമൈനുകള്‍", + "message": "മാൽവെയർ സംരക്ഷണം, സുരക്ഷ", "description": "Filter lists section name" }, "3pGroupSocial": { - "message": "Social widgets", + "message": "സോഷ്യൽ വിഡ്ജറ്റുകൾ", "description": "Filter lists section name" }, "3pGroupCookies": { - "message": "Cookie notices", + "message": "കുക്കി അറിയിപ്പുകൾ", "description": "Filter lists section name" }, "3pGroupAnnoyances": { @@ -536,15 +536,15 @@ "description": "used as a tooltip for error icon beside a list" }, "1pTrustWarning": { - "message": "Do not add filters from untrusted sources.", + "message": "വിശ്വസനീയമല്ലാത്ത ഉറവിടങ്ങളിൽ നിന്ന് ഫിൽറ്ററുകൾ ചേർക്കരുത്.", "description": "Warning against copy-pasting filters from random sources" }, "1pEnableMyFiltersLabel": { - "message": "Enable my custom filters", + "message": "എന്റെ ഇഷ്ടാനുസൃത ഫിൽറ്ററുകൾ പ്രവർത്തനക്ഷമമാക്കുക", "description": "Label for the checkbox use to enable/disable 'My filters' list" }, "1pTrustMyFiltersLabel": { - "message": "Allow custom filters requiring trust", + "message": "വിശ്വാസം ആവശ്യമുള്ള ഇഷ്ടാനുസൃത ഫിൽറ്ററുകൾ അനുവദിക്കുക", "description": "Label for the checkbox use to trust the content of 'My filters' list" }, "1pImport": { @@ -912,107 +912,107 @@ "description": "Header of 'Documentation' section in Support pane" }, "supportS1P1": { - "message": "Read the documentation at uBlock/wiki to learn about all of uBlock Origin's features.", + "message": "uBlock Origin-ന്റെ എല്ലാ സവിശേഷതകളെക്കുറിച്ചും അറിയാൻ uBlock/wiki-ൽ ഡോക്യുമെന്റേഷൻ വായിക്കുക.", "description": "First paragraph of 'Documentation' section in Support pane" }, "supportS2H": { - "message": "Questions and support", + "message": "ചോദ്യങ്ങളും പിന്തുണയും", "description": "Header of 'Questions and support' section in Support pane" }, "supportS2P1": { - "message": "Answers to questions and other kinds of help support is provided on the subreddit /r/uBlockOrigin.", + "message": "ചോദ്യങ്ങൾക്കുള്ള ഉത്തരങ്ങളും മറ്റ് തരത്തിലുള്ള സഹായ പിന്തുണയും /r/uBlockOrigin സബ്റെഡിറ്റിൽ ലഭ്യമാണ്.", "description": "First paragraph of 'Questions and support' section in Support pane" }, "supportS3H": { - "message": "Filter issues/website is broken", + "message": "ഫിൽറ്റർ പ്രശ്നങ്ങൾ/വെബ്സൈറ്റ് പ്രവർത്തിക്കുന്നില്ല", "description": "Header of 'Filter issues' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "പ്രത്യേക വെബ്സൈറ്റുകളിലെ ഫിൽറ്റർ പ്രശ്നങ്ങൾ uBlockOrigin/uAssets ഇഷ്യു ട്രാക്കറിൽ റിപ്പോർട്ട് ചെയ്യുക. ഒരു GitHub അക്കൗണ്ട് ആവശ്യമാണ്.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS3P2": { - "message": "Important: Avoid using other similarly-purposed blockers along with uBlock Origin, as this may cause filter issues on specific websites.", + "message": "പ്രധാനം: uBlock Origin-നൊപ്പം സമാനമായ ഉദ്ദേശ്യമുള്ള മറ്റ് ബ്ലോക്കറുകൾ ഉപയോഗിക്കുന്നത് ഒഴിവാക്കുക, കാരണം ഇത് പ്രത്യേക വെബ്സൈറ്റുകളിൽ ഫിൽട്ടർ പ്രശ്നങ്ങൾ ഉണ്ടാക്കിയേക്കാം.", "description": "Second paragraph of 'Filter issues' section in Support pane" }, "supportS3P3": { - "message": "Tips: Be sure your filter lists are up to date. The logger is the primary tool to diagnose filter-related issues.", + "message": "നുറുങ്ങുകൾ: നിങ്ങളുടെ ഫിൽറ്റർ ലിസ്റ്റുകൾ അപ്ഡേറ്റ് ചെയ്തിട്ടുണ്ടെന്ന് ഉറപ്പാക്കുക. ഫിൽറ്ററുമായി ബന്ധപ്പെട്ട പ്രശ്നങ്ങൾ നിർണ്ണയിക്കാനുള്ള പ്രാഥമിക ഉപകരണമാണ് ലോഗർ.", "description": "Third paragraph of 'Filter issues' section in Support pane" }, "supportS4H": { - "message": "Bug report", + "message": "ബഗ് റിപ്പോർട്ട്", "description": "Header of 'Bug report' section in Support pane" }, "supportS4P1": { - "message": "Report issues with uBlock Origin itself to the uBlockOrigin/uBlock-issue issue tracker. Requires a GitHub account.", + "message": "uBlock Origin-മായി ബന്ധപ്പെട്ട പ്രശ്നങ്ങൾ uBlockOrigin/uBlock-issue ഇഷ്യു ട്രാക്കറിൽ റിപ്പോർട്ട് ചെയ്യുക. ഒരു GitHub അക്കൗണ്ട് ആവശ്യമാണ്.", "description": "First paragraph of 'Bug report' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting Information", + "message": "പ്രശ്നപരിഹാര വിവരങ്ങൾ", "description": "Header of 'Troubleshooting Information' section in Support pane" }, "supportS5P1": { - "message": "Below is technical information that might be useful when volunteers are trying to help you solve a problem.", + "message": "ഒരു പ്രശ്നം പരിഹരിക്കാൻ സന്നദ്ധപ്രവർത്തകർ ശ്രമിക്കുമ്പോൾ ഉപയോഗപ്രദമായേക്കാവുന്ന സാങ്കേതിക വിവരങ്ങൾ ചുവടെ നൽകിയിരിക്കുന്നു.", "description": "First paragraph of 'Troubleshooting Information' section in Support pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "ഒരു ഫിൽട്ടർ പ്രശ്നം റിപ്പോർട്ട് ചെയ്യുക", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "ആവർത്തിച്ചുള്ള റിപ്പോർട്ടുകൾ ഉപയോഗിച്ച് സന്നദ്ധപ്രവർത്തകരെ ബുദ്ധിമുട്ടിക്കുന്നത് ഒഴിവാക്കാൻ, പ്രശ്നം നേരത്തെ റിപ്പോർട്ട് ചെയ്തിട്ടില്ലെന്ന് ദയവായി ഉറപ്പാക്കുക. ശ്രദ്ധിക്കുക: ബട്ടൺ ക്ലിക്ക് ചെയ്യുന്നത് പേജിന്റെ ഉത്ഭവം GitHub-ലേക്ക് അയയ്ക്കുന്നതിന് കാരണമാകും.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { - "message": "Filter lists are updated daily. Be sure your issue has not already been addressed in the most recent filter lists.", + "message": "ഫിൽറ്റർ ലിസ്റ്റുകൾ ദിവസവും അപ്ഡേറ്റ് ചെയ്യപ്പെടുന്നു. ഏറ്റവും പുതിയ ഫിൽറ്റർ ലിസ്റ്റുകളിൽ നിങ്ങളുടെ പ്രശ്നം ഇതിനകം പരിഹരിച്ചിട്ടില്ലെന്ന് ഉറപ്പാക്കുക.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S2": { - "message": "Verify that the issue still exists after reloading the problematic web page.", + "message": "പ്രശ്നമുള്ള വെബ് പേജ് വീണ്ടും ലോഡ് ചെയ്ത ശേഷം പ്രശ്നം നിലനിൽക്കുന്നുണ്ടോയെന്ന് പരിശോധിക്കുക.", "description": "A paragraph in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "വെബ് പേജിന്റെ വിലാസം:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "വെബ് പേജ്…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- ഒരു എൻട്രി തിരഞ്ഞെടുക്കുക --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "പരസ്യങ്ങളോ പരസ്യ അവശിഷ്ടങ്ങളോ കാണിക്കുന്നു", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "ഓവർലേകളോ മറ്റ് ശല്യങ്ങളോ ഉണ്ട്", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBlock Origin", + "message": "uBlock Origin-നെ കണ്ടെത്തുന്നു", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "സ്വകാര്യത-സംബന്ധമായ പ്രശ്നങ്ങൾ ഉണ്ട്", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBlock Origin is enabled", + "message": "uBlock Origin പ്രവർത്തനക്ഷമമാകുമ്പോൾ തകരാറിലാകുന്നു", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "അനാവശ്യ ടാബുകളോ വിൻഡോകളോ തുറക്കുന്നു", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "ബാഡ്വെയർ, ഫിഷിംഗ് എന്നിവയിലേക്ക് നയിക്കുന്നു", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "വെബ് പേജിനെ “NSFW” എന്ന് ലേബൽ ചെയ്യുക (“ജോലിക്ക് സുരക്ഷിതമല്ല”)", "description": "A checkbox to use for NSFW sites" }, "aboutPrivacyPolicy": { @@ -1128,7 +1128,7 @@ "description": "Firefox-specific: appears as 'uBlock₀ (off)'" }, "docblockedTitle": { - "message": "Page blocked", + "message": "പേജ് തടഞ്ഞു", "description": "Used as a title for the document-blocked page" }, "docblockedPrompt1": { @@ -1156,7 +1156,7 @@ "description": "English: Close this window" }, "docblockedDontWarn": { - "message": "Don't warn me again about this site", + "message": "ഈ സൈറ്റിനെക്കുറിച്ച് വീണ്ടും എന്നെ മുന്നറിയിപ്പ് നൽകരുത്", "description": "Label for checkbox in document-blocked page" }, "docblockedProceed": { @@ -1172,27 +1172,27 @@ "description": "English: Permanently" }, "docblockedDisable": { - "message": "Proceed", + "message": "മുന്നോട്ട് പോകുക", "description": "Button text to navigate to the blocked page" }, "docblockedRedirectPrompt": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "തടഞ്ഞ പേജ് മറ്റൊരു സൈറ്റിലേക്ക് റീഡയറക്ട് ചെയ്യാൻ ആഗ്രഹിക്കുന്നു. നിങ്ങൾ മുന്നോട്ട് പോകാൻ തിരഞ്ഞെടുക്കുകയാണെങ്കിൽ, നിങ്ങൾ നേരിട്ട് ഇങ്ങോട്ട് നാവിഗേറ്റ് ചെയ്യും: {{url}}", "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { - "message": "Reason:", + "message": "കാരണം:", "description": "The label which prepend the actual reason why a page was blocked" }, "docblockedReasonMalicious": { - "message": "Malicious", + "message": "ക്ഷുദ്രകരം", "description": "An actual reason why a page was blocked" }, "docblockedReasonTracker": { - "message": "Tracker", + "message": "ട്രാക്കർ", "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { - "message": "Disreputable", + "message": "അപ്രശസ്തമായ", "description": "An actual reason why a page was blocked" }, "cloudPush": { @@ -1248,7 +1248,7 @@ "description": "A context menu entry, present when large media elements have been blocked on the current site" }, "contextMenuViewSource": { - "message": "View source code…", + "message": "സോഴ്സ് കോഡ് കാണുക…", "description": "A context menu entry, to view the source code of the target resource" }, "shortcutCapturePlaceholder": { @@ -1264,15 +1264,15 @@ "description": "Label for buttons used to copy something to the clipboard" }, "genericSelectAll": { - "message": "Select all", + "message": "എല്ലാം തിരഞ്ഞെടുക്കുക", "description": "Label for buttons used to select all text in editor" }, "toggleCosmeticFiltering": { - "message": "Toggle cosmetic filtering", + "message": "കോസ്മെറ്റിക് ഫിൽട്ടറിംഗ് ടോഗിൾ ചെയ്യുക", "description": "Label for keyboard shortcut used to toggle cosmetic filtering" }, "toggleJavascript": { - "message": "Toggle JavaScript", + "message": "JavaScript ടോഗിൾ ചെയ്യുക", "description": "Label for keyboard shortcut used to toggle no-scripting switch" }, "relaxBlockingMode": { @@ -1300,11 +1300,11 @@ "description": "Message used in frame placeholders" }, "linterMainReport": { - "message": "Errors: {{count}}", + "message": "പിശകുകൾ: {{count}}", "description": "Summary of number of errors as reported by the linter " }, "unprocessedRequestTooltip": { - "message": "Could not filter properly at browser launch. Reload the page to ensure proper filtering.", + "message": "ബ്രൗസർ ആരംഭിക്കുമ്പോൾ ശരിയായി ഫിൽട്ടർ ചെയ്യാനായില്ല. ശരിയായ ഫിൽട്ടറിംഗ് ഉറപ്പാക്കാൻ പേജ് വീണ്ടും ലോഡ് ചെയ്യുക.", "description": "A warning which will appear in the popup panel if needed" }, "dummy": { diff --git a/src/_locales/mr/messages.json b/src/_locales/mr/messages.json index 9c954e37c1778..086b191dafe2d 100644 --- a/src/_locales/mr/messages.json +++ b/src/_locales/mr/messages.json @@ -12,15 +12,15 @@ "description": "English: uBlock₀ — Dashboard" }, "dashboardUnsavedWarning": { - "message": "Warning: you have unsaved changes!", + "message": "सावधान: तुमच्याकडे जतन न केलेले बदल आहेत!", "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "Stay here", + "message": "येथेच रहा", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { - "message": "Ignore", + "message": "दुर्लक्ष करा", "description": "Label for button to ignore unsaved changes" }, "settingsPageName": { @@ -44,7 +44,7 @@ "description": "appears as tab name in dashboard" }, "shortcutsPageName": { - "message": "Shortcuts", + "message": "शॉर्टकट", "description": "appears as tab name in dashboard" }, "statsPageName": { @@ -56,11 +56,11 @@ "description": "appears as tab name in dashboard" }, "supportPageName": { - "message": "Support", + "message": "सहाय्य", "description": "appears as tab name in dashboard" }, "assetViewerPageName": { - "message": "uBlock₀ — Asset viewer", + "message": "uBlock₀ — संपत्ती दर्शक", "description": "Title for the asset viewer page" }, "advancedSettingsPageName": { @@ -100,15 +100,15 @@ "description": "English: or" }, "popupBlockedOnThisPage_v2": { - "message": "Blocked on this page", + "message": "या पृष्ठावर अवरोधित", "description": "For the new mobile-friendly popup design" }, "popupBlockedSinceInstall_v2": { - "message": "Blocked since install", + "message": "स्थापनेपासून अवरोधित", "description": "For the new mobile-friendly popup design" }, "popupDomainsConnected_v2": { - "message": "Domains connected", + "message": "जोडलेले डोमेन", "description": "For the new mobile-friendly popup design" }, "popupTipDashboard": { @@ -116,7 +116,7 @@ "description": "English: Click to open the dashboard" }, "popupTipZapper": { - "message": "Enter element zapper mode", + "message": "एलिमेंट झापर मोडमध्ये प्रवेश करा", "description": "Tooltip for the element-zapper icon in the popup panel" }, "popupTipPicker": { @@ -128,7 +128,7 @@ "description": "Tooltip used for the logger icon in the panel" }, "popupTipReport": { - "message": "Report an issue on this website", + "message": "या वेबसाइटवर समस्या कळवा", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipNoPopups": { @@ -136,11 +136,11 @@ "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoPopups1": { - "message": "Click to block all popups on this site", + "message": "या साइटवरील सर्व पॉपअप अवरोधित करण्यासाठी क्लिक करा", "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoPopups2": { - "message": "Click to no longer block all popups on this site", + "message": "या साइटवरील सर्व पॉपअप पुन्हा अवरोधित न करण्यासाठी क्लिक करा", "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoLargeMedia": { @@ -148,11 +148,11 @@ "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoLargeMedia1": { - "message": "Click to block large media elements on this site", + "message": "या साइटवरील मोठे मीडिया एलिमेंट अवरोधित करण्यासाठी क्लिक करा", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoLargeMedia2": { - "message": "Click to no longer block large media elements on this site", + "message": "या साइटवरील मोठे मीडिया एलिमेंट पुन्हा अवरोधित न करण्यासाठी क्लिक करा", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoCosmeticFiltering": { @@ -160,47 +160,47 @@ "description": "Tooltip for the no-cosmetic-filtering per-site switch" }, "popupTipNoCosmeticFiltering1": { - "message": "Click to disable cosmetic filtering on this site", + "message": "या साइटवरील कॉस्मेटिक फिल्टरिंग अक्षम करण्यासाठी क्लिक करा", "description": "Tooltip for the no-cosmetic-filtering per-site switch" }, "popupTipNoCosmeticFiltering2": { - "message": "Click to enable cosmetic filtering on this site", + "message": "या साइटवरील कॉस्मेटिक फिल्टरिंग सक्षम करण्यासाठी क्लिक करा", "description": "Tooltip for the no-cosmetic-filtering per-site switch" }, "popupTipNoRemoteFonts": { - "message": "Toggle the blocking of remote fonts for this site", + "message": "या साइटसाठी रिमोट फॉन्टचे अवरोधन टॉगल करा", "description": "Tooltip for the no-remote-fonts per-site switch" }, "popupTipNoRemoteFonts1": { - "message": "Click to block remote fonts on this site", + "message": "या साइटवरील रिमोट फॉन्ट अवरोधित करण्यासाठी क्लिक करा", "description": "Tooltip for the no-remote-fonts per-site switch" }, "popupTipNoRemoteFonts2": { - "message": "Click to no longer block remote fonts on this site", + "message": "या साइटवरील रिमोट फॉन्ट पुन्हा अवरोधित न करण्यासाठी क्लिक करा", "description": "Tooltip for the no-remote-fonts per-site switch" }, "popupTipNoScripting1": { - "message": "Click to disable JavaScript on this site", + "message": "या साइटवरील JavaScript अक्षम करण्यासाठी क्लिक करा", "description": "Tooltip for the no-scripting per-site switch" }, "popupTipNoScripting2": { - "message": "Click to no longer disable JavaScript on this site", + "message": "या साइटवरील JavaScript पुन्हा अक्षम न करण्यासाठी क्लिक करा", "description": "Tooltip for the no-scripting per-site switch" }, "popupNoPopups_v2": { - "message": "Pop-up windows", + "message": "पॉप-अप विंडो", "description": "Caption for the no-popups per-site switch" }, "popupNoLargeMedia_v2": { - "message": "Large media elements", + "message": "मोठे मीडिया एलिमेंट", "description": "Caption for the no-large-media per-site switch" }, "popupNoCosmeticFiltering_v2": { - "message": "Cosmetic filtering", + "message": "कॉस्मेटिक फिल्टरिंग", "description": "Caption for the no-cosmetic-filtering per-site switch" }, "popupNoRemoteFonts_v2": { - "message": "Remote fonts", + "message": "रिमोट फॉन्ट", "description": "Caption for the no-remote-fonts per-site switch" }, "popupNoScripting_v2": { @@ -208,27 +208,27 @@ "description": "Caption for the no-scripting per-site switch" }, "popupMoreButton_v2": { - "message": "More", + "message": "अधिक", "description": "Label to be used to show popup panel sections" }, "popupLessButton_v2": { - "message": "Less", + "message": "कमी", "description": "Label to be used to hide popup panel sections" }, "popupTipGlobalRules": { - "message": "Global rules: this column is for rules which apply to all sites.", + "message": "जागतिक नियम: हा स्तंभ सर्व साइट्सना लागू होणाऱ्या नियमांसाठी आहे.", "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Local rules: this column is for rules which apply to the current site only.", + "message": "स्थानिक नियम: हा स्तंभ फक्त सध्याच्या साइटला लागू होणाऱ्या नियमांसाठी आहे.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { - "message": "Click to make your changes permanent.", + "message": "तुमचे बदल कायमस्वरूपी करण्यासाठी क्लिक करा.", "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." }, "popupTipRevertRules": { - "message": "Click to revert your changes.", + "message": "तुमचे बदल पूर्ववत करण्यासाठी क्लिक करा.", "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." }, "popupAnyRulePrompt": { @@ -248,23 +248,23 @@ "description": "" }, "popupInlineScriptRulePrompt": { - "message": "inline scripts", + "message": "इनलाइन स्क्रिप्ट", "description": "" }, "popup1pScriptRulePrompt": { - "message": "1st-party scripts", + "message": "प्रथम-पक्ष स्क्रिप्ट", "description": "" }, "popup3pScriptRulePrompt": { - "message": "3rd-party scripts", + "message": "तृतीय-पक्ष स्क्रिप्ट", "description": "" }, "popup3pFrameRulePrompt": { - "message": "3rd-party frames", + "message": "तृतीय-पक्ष फ्रेम", "description": "" }, "popupHitDomainCountPrompt": { - "message": "domains connected", + "message": "जोडलेले डोमेन", "description": "appears in popup" }, "popupHitDomainCount": { @@ -272,15 +272,15 @@ "description": "appears in popup" }, "popupVersion": { - "message": "Version", + "message": "आवृत्ती", "description": "Example of use: Version 1.26.4" }, "popup3pScriptFilter": { - "message": "script", + "message": "स्क्रिप्ट", "description": "Appears as an option to filter out firewall rows" }, "popup3pFrameFilter": { - "message": "frame", + "message": "फ्रेम", "description": "Appears as an option to filter out firewall rows" }, "pickerCreate": { @@ -296,7 +296,7 @@ "description": "English: Quit" }, "pickerPreview": { - "message": "Preview", + "message": "पूर्वावलोकन", "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" }, "pickerNetFilters": { @@ -324,7 +324,7 @@ "description": "English: Show the number of blocked requests on the icon" }, "settingsTooltipsPrompt": { - "message": "Disable tooltips", + "message": "टूलटिप्स अक्षम करा", "description": "A checkbox in the Settings pane" }, "settingsContextMenuPrompt": { @@ -332,79 +332,79 @@ "description": "English: Make use of context menu where appropriate" }, "settingsColorBlindPrompt": { - "message": "Color-blind friendly", + "message": "रंगांधळ्यांसाठी अनुकूल", "description": "English: Color-blind friendly" }, "settingsAppearance": { - "message": "Appearance", + "message": "दिसणे", "description": "Section for controlling user interface appearance" }, "settingsThemeLabel": { - "message": "Theme", + "message": "थीम", "description": "Label for checkbox to enable a custom dark theme" }, "settingsThemeAccent0Label": { - "message": "Custom accent color", + "message": "सानुकूल ऍक्सेंट रंग", "description": "Label for checkbox to pick an accent color" }, "settingsCloudStorageEnabledPrompt": { - "message": "Enable cloud storage support", + "message": "क्लाउड स्टोरेज समर्थन सक्षम करा", "description": "" }, "settingsAdvancedUserPrompt": { - "message": "I am an advanced user", + "message": "मी प्रगत वापरकर्ता आहे", "description": "Checkbox to let user access advanced, technical features" }, "settingsPrefetchingDisabledPrompt": { - "message": "Disable pre-fetching (to prevent any connection for blocked network requests)", + "message": "प्री-फेचिंग अक्षम करा (अवरोधित नेटवर्क विनंत्यांसाठी कोणतेही कनेक्शन रोखण्यासाठी)", "description": "English: " }, "settingsHyperlinkAuditingDisabledPrompt": { - "message": "Disable hyperlink auditing", + "message": "हायपरलिंक ऑडिटिंग अक्षम करा", "description": "English: " }, "settingsWebRTCIPAddressHiddenPrompt": { - "message": "Prevent WebRTC from leaking local IP addresses", + "message": "WebRTC ला स्थानिक IP पत्ते लीक करण्यापासून रोखा", "description": "English: " }, "settingPerSiteSwitchGroup": { - "message": "Default behavior", + "message": "डीफॉल्ट वर्तन", "description": "" }, "settingPerSiteSwitchGroupSynopsis": { - "message": "These default behaviors can be overridden on a per-site basis", + "message": "ही डीफॉल्ट वर्तने प्रति-साइट आधारावर बदलली जाऊ शकतात", "description": "" }, "settingsNoCosmeticFilteringPrompt": { - "message": "Disable cosmetic filtering", + "message": "कॉस्मेटिक फिल्टरिंग अक्षम करा", "description": "" }, "settingsNoLargeMediaPrompt": { - "message": "Block media elements larger than {{input}} KB", + "message": "{{input}} KB पेक्षा मोठे मीडिया एलिमेंट अवरोधित करा", "description": "" }, "settingsNoRemoteFontsPrompt": { - "message": "Block remote fonts", + "message": "रिमोट फॉन्ट अवरोधित करा", "description": "" }, "settingsNoScriptingPrompt": { - "message": "Disable JavaScript", + "message": "JavaScript अक्षम करा", "description": "The default state for the per-site no-scripting switch" }, "settingsNoCSPReportsPrompt": { - "message": "Block CSP reports", + "message": "CSP अहवाल अवरोधित करा", "description": "background information: https://github.com/gorhill/uBlock/issues/3150" }, "settingsUncloakCnamePrompt": { - "message": "Uncloak canonical names", + "message": "कॅनोनिकल नावे अनक्लोक करा", "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" }, "settingsAdvanced": { - "message": "Advanced", + "message": "प्रगत", "description": "Section for controlling advanced-user settings" }, "settingsAdvancedSynopsis": { - "message": "Features suitable only for technical users", + "message": "फक्त तांत्रिक वापरकर्त्यांसाठी योग्य वैशिष्ट्ये", "description": "Description of section controlling advanced-user settings" }, "settingsAdvancedUserSettings": { @@ -448,15 +448,15 @@ "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." }, "3pIgnoreGenericCosmeticFilters": { - "message": "Ignore generic cosmetic filters", + "message": "सामान्य कॉस्मेटिक फिल्टरकडे दुर्लक्ष करा", "description": "This will cause uBO to ignore all generic cosmetic filters." }, "3pIgnoreGenericCosmeticFiltersInfo": { - "message": "Generic cosmetic filters are those cosmetic filters which are meant to apply on all web sites. Enabling this option will eliminate the memory and CPU overhead added to web pages as a result of handling generic cosmetic filters.\n\nIt is recommended to enable this option on less powerful devices.", + "message": "सामान्य कॉस्मेटिक फिल्टर म्हणजे ते कॉस्मेटिक फिल्टर जे सर्व वेबसाइट्सवर लागू करण्यासाठी आहेत. हा पर्याय सक्षम केल्याने सामान्य कॉस्मेटिक फिल्टर हाताळण्याच्या परिणामी वेब पृष्ठांमध्ये जोडलेला मेमरी आणि CPU ओव्हरहेड काढून टाकला जाईल.\n\nकमी शक्तिशाली उपकरणांवर हा पर्याय सक्षम करण्याची शिफारस केली जाते.", "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." }, "3pSuspendUntilListsAreLoaded": { - "message": "Suspend network activity until all filter lists are loaded", + "message": "सर्व फिल्टर याद्या लोड होईपर्यंत नेटवर्क क्रियाकलाप स्थगित करा", "description": "A checkbox in the 'Filter lists' pane" }, "3pListsOfBlockedHostsHeader": { @@ -468,7 +468,7 @@ "description": "English: Apply changes" }, "3pGroupDefault": { - "message": "Built-in", + "message": "अंगभूत", "description": "Filter lists section name" }, "3pGroupAds": { @@ -480,15 +480,15 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "मालवेअर डोमेन", + "message": "मालवेअरपासून संरक्षण, सुरक्षा", "description": "Filter lists section name" }, "3pGroupSocial": { - "message": "Social widgets", + "message": "सोशल विजेट्स", "description": "Filter lists section name" }, "3pGroupCookies": { - "message": "Cookie notices", + "message": "कुकी सूचना", "description": "Filter lists section name" }, "3pGroupAnnoyances": { @@ -508,7 +508,7 @@ "description": "Filter lists section name" }, "3pImport": { - "message": "Import…", + "message": "आयात करा…", "description": "The label for the checkbox used to import external filter lists" }, "3pExternalListsHint": { @@ -520,31 +520,31 @@ "description": "used as a tooltip for the out-of-date icon beside a list" }, "3pViewContent": { - "message": "view content", + "message": "सामग्री पहा", "description": "used as a tooltip for eye icon beside a list" }, "3pLastUpdate": { - "message": "Last update: {{ago}}.\nClick to force an update.", + "message": "शेवटचे अद्यतन: {{ago}}.\nअद्यतन भाग पाडण्यासाठी क्लिक करा.", "description": "used as a tooltip for the clock icon beside a list" }, "3pUpdating": { - "message": "Updating…", + "message": "अद्यतनित करत आहे…", "description": "used as a tooltip for the spinner icon beside a list" }, "3pNetworkError": { - "message": "A network error prevented the resource from being updated.", + "message": "नेटवर्क त्रुटीमुळे संसाधन अद्यतनित होऊ शकले नाही.", "description": "used as a tooltip for error icon beside a list" }, "1pTrustWarning": { - "message": "Do not add filters from untrusted sources.", + "message": "अविश्वसनीय स्रोतांकडून फिल्टर जोडू नका.", "description": "Warning against copy-pasting filters from random sources" }, "1pEnableMyFiltersLabel": { - "message": "Enable my custom filters", + "message": "माझे सानुकूल फिल्टर सक्षम करा", "description": "Label for the checkbox use to enable/disable 'My filters' list" }, "1pTrustMyFiltersLabel": { - "message": "Allow custom filters requiring trust", + "message": "विश्वास आवश्यक असलेले सानुकूल फिल्टर अनुमती द्या", "description": "Label for the checkbox use to trust the content of 'My filters' list" }, "1pImport": { @@ -576,7 +576,7 @@ "description": "This will remove all temporary rules" }, "rulesCommit": { - "message": "Commit", + "message": "कमिट करा", "description": "This will persist temporary rules" }, "rulesEdit": { @@ -584,19 +584,19 @@ "description": "Will enable manual-edit mode (textarea)" }, "rulesEditSave": { - "message": "Save", + "message": "जतन करा", "description": "Will save manually-edited content and exit manual-edit mode" }, "rulesEditDiscard": { - "message": "Discard", + "message": "टाकून द्या", "description": "Will discard manually-edited content and exit manual-edit mode" }, "rulesImport": { - "message": "Import from file…", + "message": "फाइलमधून आयात करा…", "description": "" }, "rulesExport": { - "message": "Export to file…", + "message": "फाइलमध्ये निर्यात करा…", "description": "Button in the 'My rules' pane" }, "rulesDefaultFileName": { @@ -604,27 +604,27 @@ "description": "default file name to use" }, "rulesHint": { - "message": "List of your dynamic filtering rules.", + "message": "तुमच्या डायनॅमिक फिल्टरिंग नियमांची यादी.", "description": "English: List of your dynamic filtering rules." }, "rulesFormatHint": { - "message": "Rule syntax: source destination type action (full documentation).", + "message": "नियम सिंटॅक्स: स्रोत गंतव्य प्रकार क्रिया (संपूर्ण दस्तऐवजीकरण).", "description": "English: dynamic rule syntax and full documentation." }, "rulesSort": { - "message": "Sort:", + "message": "क्रमवारी लावा:", "description": "English: label for sort option." }, "rulesSortByType": { - "message": "Rule type", + "message": "नियम प्रकार", "description": "English: a sort option for list of rules." }, "rulesSortBySource": { - "message": "Source", + "message": "स्रोत", "description": "English: a sort option for list of rules." }, "rulesSortByDestination": { - "message": "Destination", + "message": "गंतव्य", "description": "English: a sort option for list of rules." }, "whitelistPrompt": { @@ -664,59 +664,59 @@ "description": "English: Filter" }, "logAll": { - "message": "All", + "message": "सर्व", "description": "Appears in the logger's tab selector" }, "logBehindTheScene": { - "message": "Tabless", + "message": "टॅबशिवाय", "description": "Pretty name for behind-the-scene network requests" }, "loggerCurrentTab": { - "message": "Current tab", + "message": "सध्याचा टॅब", "description": "Appears in the logger's tab selector" }, "loggerReloadTip": { - "message": "Reload the tab content", + "message": "टॅब सामग्री पुन्हा लोड करा", "description": "Tooltip for the reload button in the logger page" }, "loggerDomInspectorTip": { - "message": "Toggle the DOM inspector", + "message": "DOM इन्स्पेक्टर टॉगल करा", "description": "Tooltip for the DOM inspector button in the logger page" }, "loggerPopupPanelTip": { - "message": "Toggle the popup panel", + "message": "पॉपअप पॅनेल टॉगल करा", "description": "Tooltip for the popup panel button in the logger page" }, "loggerInfoTip": { - "message": "uBlock Origin wiki: The logger", + "message": "uBlock Origin विकी: लॉगर", "description": "Tooltip for the top-right info label in the logger page" }, "loggerClearTip": { - "message": "Clear logger", + "message": "लॉगर साफ करा", "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" }, "loggerPauseTip": { - "message": "Pause logger (discard all incoming data)", + "message": "लॉगर विराम द्या (सर्व येणारा डेटा टाकून द्या)", "description": "Tooltip for the pause button in the logger page" }, "loggerUnpauseTip": { - "message": "Unpause logger", + "message": "लॉगर विराम रद्द करा", "description": "Tooltip for the play button in the logger page" }, "loggerRowFiltererButtonTip": { - "message": "Toggle logger filtering", + "message": "लॉगर फिल्टरिंग टॉगल करा", "description": "Tooltip for the row filterer button in the logger page" }, "logFilterPrompt": { - "message": "filter logger content", + "message": "लॉगर सामग्री फिल्टर करा", "description": "Placeholder string for logger output filtering input field" }, "loggerRowFiltererBuiltinTip": { - "message": "Logger filtering options", + "message": "लॉगर फिल्टरिंग पर्याय", "description": "Tooltip for the button to bring up logger output filtering options" }, "loggerRowFiltererBuiltinNot": { - "message": "Not", + "message": "नाही", "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltinEventful": { @@ -724,55 +724,55 @@ "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" }, "loggerRowFiltererBuiltinBlocked": { - "message": "blocked", + "message": "अवरोधित", "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltinAllowed": { - "message": "allowed", + "message": "परवानगी दिलेली", "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltinModified": { - "message": "modified", + "message": "सुधारित", "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltin1p": { - "message": "1st-party", + "message": "प्रथम-पक्ष", "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltin3p": { - "message": "3rd-party", + "message": "तृतीय-पक्ष", "description": "A keyword in the built-in row filtering expression" }, "loggerEntryDetailsHeader": { - "message": "Details", + "message": "तपशील", "description": "Small header to identify the 'Details' pane for a specific logger entry" }, "loggerEntryDetailsFilter": { - "message": "Filter", + "message": "फिल्टर", "description": "Label to identify a filter field" }, "loggerEntryDetailsFilterList": { - "message": "Filter list", + "message": "फिल्टर यादी", "description": "Label to identify a filter list field" }, "loggerEntryDetailsRule": { - "message": "Rule", + "message": "नियम", "description": "Label to identify a rule field" }, "loggerEntryDetailsContext": { - "message": "Context", + "message": "संदर्भ", "description": "Label to identify a context field (typically a hostname)" }, "loggerEntryDetailsRootContext": { - "message": "Root context", + "message": "मूळ संदर्भ", "description": "Label to identify a root context field (typically a hostname)" }, "loggerEntryDetailsPartyness": { - "message": "Partyness", + "message": "पार्टीनेस", "description": "Label to identify a field providing partyness information" }, "loggerEntryDetailsType": { - "message": "Type", + "message": "प्रकार", "description": "Label to identify the type of an entry" }, "loggerEntryDetailsURL": { @@ -780,115 +780,115 @@ "description": "Label to identify the URL of an entry" }, "loggerURLFilteringHeader": { - "message": "URL rule", + "message": "URL नियम", "description": "Small header to identify the dynamic URL filtering section" }, "loggerURLFilteringContextLabel": { - "message": "Context:", + "message": "संदर्भ:", "description": "Label for the context selector" }, "loggerURLFilteringTypeLabel": { - "message": "Type:", + "message": "प्रकार:", "description": "Label for the type selector" }, "loggerStaticFilteringHeader": { - "message": "Static filter", + "message": "स्थिर फिल्टर", "description": "Small header to identify the static filtering section" }, "loggerStaticFilteringSentence": { - "message": "{{action}} network requests of {{type}} {{br}}which URL address matches {{url}} {{br}}and which originates {{origin}},{{br}}{{importance}} there is a matching exception filter.", + "message": "{{action}} {{type}} च्या नेटवर्क विनंती {{br}}ज्याचा URL पत्ता {{url}} शी जुळतो {{br}}आणि ज्याचा उगम {{origin}} आहे,{{br}}{{importance}} एक जुळणारा अपवाद फिल्टर आहे.", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartBlock": { - "message": "Block", + "message": "अवरोधित करा", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartAllow": { - "message": "Allow", + "message": "परवानगी द्या", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartType": { - "message": "type “{{type}}”", + "message": "“{{type}}” प्रकार", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartAnyType": { - "message": "any type", + "message": "कोणताही प्रकार", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartOrigin": { - "message": "from “{{origin}}”", + "message": "“{{origin}}” पासून", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartAnyOrigin": { - "message": "from anywhere", + "message": "कोठूनही", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartNotImportant": { - "message": "except when", + "message": "जोपर्यंत", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartImportant": { - "message": "even if", + "message": "जरी", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringFinderSentence1": { - "message": "Static filter {{filter}} found in:", + "message": "स्थिर फिल्टर {{filter}} यामध्ये आढळले:", "description": "Below this sentence, the filter list(s) in which the filter was found" }, "loggerStaticFilteringFinderSentence2": { - "message": "Static filter could not be found in any of the currently enabled filter lists", + "message": "सध्या सक्षम केलेल्या कोणत्याही फिल्टर यादीत स्थिर फिल्टर सापडला नाही", "description": "Message to show when a filter cannot be found in any filter lists" }, "loggerSettingDiscardPrompt": { - "message": "Logger entries which do not fulfill all three conditions below will be automatically discarded:", + "message": "खालील सर्व तीन अटी पूर्ण न करणाऱ्या लॉगर नोंदी स्वयंचलितपणे टाकून दिल्या जातील:", "description": "Logger setting: A sentence to describe the purpose of the settings below" }, "loggerSettingPerEntryMaxAge": { - "message": "Preserve entries from the last {{input}} minutes", + "message": "गेल्या {{input}} मिनिटांतील नोंदी जतन करा", "description": "A logger setting" }, "loggerSettingPerTabMaxLoads": { - "message": "Preserve at most {{input}} page loads per tab", + "message": "प्रति टॅब कमाल {{input}} पृष्ठ लोड जतन करा", "description": "A logger setting" }, "loggerSettingPerTabMaxEntries": { - "message": "Preserve at most {{input}} entries per tab", + "message": "प्रति टॅब कमाल {{input}} नोंदी जतन करा", "description": "A logger setting" }, "loggerSettingPerEntryLineCount": { - "message": "Use {{input}} lines per entry in vertically expanded mode", + "message": "अनुलंब विस्तारित मोडमध्ये प्रति नोंद {{input}} ओळी वापरा", "description": "A logger setting" }, "loggerSettingHideColumnsPrompt": { - "message": "Hide columns:", + "message": "स्तंभ लपवा:", "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" }, "loggerSettingHideColumnTime": { - "message": "{{input}} Time", + "message": "{{input}} वेळ", "description": "A label for the time column" }, "loggerSettingHideColumnFilter": { - "message": "{{input}} Filter/rule", + "message": "{{input}} फिल्टर/नियम", "description": "A label for the filter or rule column" }, "loggerSettingHideColumnContext": { - "message": "{{input}} Context", + "message": "{{input}} संदर्भ", "description": "A label for the context column" }, "loggerSettingHideColumnPartyness": { - "message": "{{input}} Partyness", + "message": "{{input}} पार्टीनेस", "description": "A label for the partyness column" }, "loggerExportFormatList": { - "message": "List", + "message": "यादी", "description": "Label for radio-button to pick export format" }, "loggerExportFormatTable": { - "message": "Table", + "message": "सारणी", "description": "Label for radio-button to pick export format" }, "loggerExportEncodePlain": { - "message": "Plain", + "message": "साधा", "description": "Label for radio-button to pick export text format" }, "loggerExportEncodeMarkdown": { @@ -896,127 +896,127 @@ "description": "Label for radio-button to pick export text format" }, "supportOpenButton": { - "message": "Open", + "message": "उघडा", "description": "Text for button which open an external web page in Support pane" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "GitHub वर नवीन अहवाल तयार करा", "description": "Text for button which open an external web page in Support pane" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "GitHub वर समान अहवाल शोधा", "description": "A clickable link in the filter issue reporter section" }, "supportS1H": { - "message": "Documentation", + "message": "दस्तऐवजीकरण", "description": "Header of 'Documentation' section in Support pane" }, "supportS1P1": { - "message": "Read the documentation at uBlock/wiki to learn about all of uBlock Origin's features.", + "message": "uBlock Origin ची सर्व वैशिष्ट्ये जाणून घेण्यासाठी uBlock/wiki वर दस्तऐवजीकरण वाचा.", "description": "First paragraph of 'Documentation' section in Support pane" }, "supportS2H": { - "message": "Questions and support", + "message": "प्रश्न आणि समर्थन", "description": "Header of 'Questions and support' section in Support pane" }, "supportS2P1": { - "message": "Answers to questions and other kinds of help support is provided on the subreddit /r/uBlockOrigin.", + "message": "प्रश्नांची उत्तरे आणि इतर प्रकारची मदत /r/uBlockOrigin या सबरेडिटवर उपलब्ध आहे.", "description": "First paragraph of 'Questions and support' section in Support pane" }, "supportS3H": { - "message": "Filter issues/website is broken", + "message": "फिल्टर समस्या/वेबसाइट खराब आहे", "description": "Header of 'Filter issues' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "विशिष्ट वेबसाइट्सवरील फिल्टर समस्या uBlockOrigin/uAssets समस्या ट्रॅकरला कळवा. GitHub खाते आवश्यक आहे.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS3P2": { - "message": "Important: Avoid using other similarly-purposed blockers along with uBlock Origin, as this may cause filter issues on specific websites.", + "message": "महत्त्वाचे: uBlock Origin सोबत इतर समान उद्देशाचे ब्लॉकर वापरणे टाळा, कारण यामुळे विशिष्ट वेबसाइट्सवर फिल्टर समस्या उद्भवू शकतात.", "description": "Second paragraph of 'Filter issues' section in Support pane" }, "supportS3P3": { - "message": "Tips: Be sure your filter lists are up to date. The logger is the primary tool to diagnose filter-related issues.", + "message": "टिपा: तुमच्या फिल्टर याद्या अद्ययावत असल्याची खात्री करा. फिल्टर-संबंधित समस्यांचे निदान करण्यासाठी लॉगर हे प्राथमिक साधन आहे.", "description": "Third paragraph of 'Filter issues' section in Support pane" }, "supportS4H": { - "message": "Bug report", + "message": "बग अहवाल", "description": "Header of 'Bug report' section in Support pane" }, "supportS4P1": { - "message": "Report issues with uBlock Origin itself to the uBlockOrigin/uBlock-issue issue tracker. Requires a GitHub account.", + "message": "uBlock Origin मधीलच समस्या uBlockOrigin/uBlock-issue समस्या ट्रॅकरला कळवा. GitHub खाते आवश्यक आहे.", "description": "First paragraph of 'Bug report' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting Information", + "message": "समस्या निवारण माहिती", "description": "Header of 'Troubleshooting Information' section in Support pane" }, "supportS5P1": { - "message": "Below is technical information that might be useful when volunteers are trying to help you solve a problem.", + "message": "जेव्हा स्वयंसेवक तुम्हाला समस्या सोडवण्यास मदत करण्याचा प्रयत्न करतात तेव्हा उपयुक्त ठरू शकणारी तांत्रिक माहिती खाली दिली आहे.", "description": "First paragraph of 'Troubleshooting Information' section in Support pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "फिल्टर समस्या कळवा", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "स्वयंसेवकांवर डुप्लिकेट अहवालांचा भार टाळण्यासाठी, कृपया ही समस्या आधीपासून अहवाल केली गेली नाही याची पडताळणी करा. सूचना: बटण क्लिक केल्याने पृष्ठाचे मूळ (origin) GitHub वर पाठवले जाईल.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { - "message": "Filter lists are updated daily. Be sure your issue has not already been addressed in the most recent filter lists.", + "message": "फिल्टर याद्या दररोज अद्यतनित केल्या जातात. तुमची समस्या अगदी अलीकडील फिल्टर याद्यांमध्ये आधीच सोडवली गेली नाही याची खात्री करा.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S2": { - "message": "Verify that the issue still exists after reloading the problematic web page.", + "message": "समस्याग्रस्त वेब पृष्ठ पुन्हा लोड केल्यानंतर समस्या अजूनही अस्तित्वात आहे याची पडताळणी करा.", "description": "A paragraph in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "वेब पृष्ठाचा पत्ता:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "वेब पृष्ठ…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- एक नोंद निवडा --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "जाहिराती किंवा जाहिरातीचे अवशेष दाखवते", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "ओव्हरले किंवा इतर त्रासदायक घटक आहेत", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBlock Origin", + "message": "uBlock Origin शोधते", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "गोपनीयता-संबंधित समस्या आहेत", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBlock Origin is enabled", + "message": "uBlock Origin सक्षम असताना कार्यात अडथळा येतो", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "अवांछित टॅब किंवा विंडो उघडते", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "बॅडवेअर, फिशिंगकडे नेतो", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "वेब पृष्ठाला “NSFW” (“Not Safe For Work”) म्हणून लेबल करा", "description": "A checkbox to use for NSFW sites" }, "aboutPrivacyPolicy": { - "message": "Privacy policy", + "message": "गोपनीयता धोरण", "description": "Link to privacy policy on GitHub (English)" }, "aboutChangelog": { @@ -1032,27 +1032,27 @@ "description": "English: Contributors" }, "aboutSourceCode": { - "message": "Source code", + "message": "सोर्स कोड", "description": "Link text to source code repo" }, "aboutTranslations": { - "message": "Translations", + "message": "अनुवाद", "description": "Link text to translations repo" }, "aboutFilterLists": { - "message": "Filter lists", + "message": "फिल्टर याद्या", "description": "Link text to uBO's own filter lists repo" }, "aboutDependencies": { - "message": "External dependencies (GPLv3-compatible):", + "message": "बाह्य अवलंबित्वे (GPLv3-सुसंगत):", "description": "Shown in the About pane" }, "aboutCDNs": { - "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "message": "uBO च्या स्वतःच्या फिल्टर याद्या खालील CDN वर विनामूल्य होस्ट केल्या आहेत:", "description": "Shown in the About pane" }, "aboutCDNsInfo": { - "message": "A randomly picked CDN is used when a filter list needs to be updated.", + "message": "जेव्हा फिल्टर यादी अद्यतनित करण्याची आवश्यकता असते तेव्हा यादृच्छिकपणे निवडलेले CDN वापरले जाते.", "description": "Shown in the About pane" }, "aboutBackupDataButton": { @@ -1076,7 +1076,7 @@ "description": "Message asking user to confirm restore" }, "aboutRestoreDataError": { - "message": "The data could not be read or is invalid", + "message": "डेटा वाचला जाऊ शकला नाही किंवा तो अवैध आहे", "description": "Message to display when an error occurred during restore" }, "aboutResetDataConfirm": { @@ -1088,123 +1088,123 @@ "description": "English: Network error: {{msg}}" }, "subscribeButton": { - "message": "Subscribe", + "message": "सदस्यता घ्या", "description": "For the button used to subscribe to a filter list" }, "elapsedOneMinuteAgo": { - "message": "a minute ago", + "message": "एक मिनिटापूर्वी", "description": "English: a minute ago" }, "elapsedManyMinutesAgo": { - "message": "{{value}} minutes ago", + "message": "{{value}} मिनिटांपूर्वी", "description": "English: {{value}} minutes ago" }, "elapsedOneHourAgo": { - "message": "an hour ago", + "message": "एक तासापूर्वी", "description": "English: an hour ago" }, "elapsedManyHoursAgo": { - "message": "{{value}} hours ago", + "message": "{{value}} तासांपूर्वी", "description": "English: {{value}} hours ago" }, "elapsedOneDayAgo": { - "message": "a day ago", + "message": "एक दिवसापूर्वी", "description": "English: a day ago" }, "elapsedManyDaysAgo": { - "message": "{{value}} days ago", + "message": "{{value}} दिवसांपूर्वी", "description": "English: {{value}} days ago" }, "showDashboardButton": { - "message": "Show Dashboard", + "message": "डॅशबोर्ड दाखवा", "description": "Firefox/Fennec-specific: Show Dashboard" }, "showNetworkLogButton": { - "message": "Show Logger", + "message": "लॉगर दाखवा", "description": "Firefox/Fennec-specific: Show Logger" }, "fennecMenuItemBlockingOff": { - "message": "off", + "message": "बंद", "description": "Firefox-specific: appears as 'uBlock₀ (off)'" }, "docblockedTitle": { - "message": "Page blocked", + "message": "पृष्ठ अवरोधित", "description": "Used as a title for the document-blocked page" }, "docblockedPrompt1": { - "message": "uBlock Origin has prevented the following page from loading:", + "message": "uBlock Origin ने खालील पृष्ठ लोड होण्यापासून रोखले आहे:", "description": "Used in the strict-blocking page" }, "docblockedPrompt2": { - "message": "This happened because of the following filter:", + "message": "खालील फिल्टरमुळे असे घडले:", "description": "Used in the strict-blocking page" }, "docblockedNoParamsPrompt": { - "message": "without parameters", + "message": "पॅरामीटर्सशिवाय", "description": "label to be used for the parameter-less URL: https://cloud.githubusercontent.com/assets/585534/9832014/bfb1b8f0-593b-11e5-8a27-fba472a5529a.png" }, "docblockedFoundIn": { - "message": "The filter has been found in:", + "message": "फिल्टर यामध्ये आढळला आहे:", "description": "English: List of filter list names follows" }, "docblockedBack": { - "message": "Go back", + "message": "मागे जा", "description": "English: Go back" }, "docblockedClose": { - "message": "Close this window", + "message": "ही विंडो बंद करा", "description": "English: Close this window" }, "docblockedDontWarn": { - "message": "Don't warn me again about this site", + "message": "या साइटबद्दल मला पुन्हा इशारा देऊ नका", "description": "Label for checkbox in document-blocked page" }, "docblockedProceed": { - "message": "Disable strict blocking for {{hostname}}", + "message": "{{hostname}} साठी कठोर अवरोधन अक्षम करा", "description": "English: Disable strict blocking for {{hostname}} ..." }, "docblockedDisableTemporary": { - "message": "Temporarily", + "message": "तात्पुरते", "description": "English: Temporarily" }, "docblockedDisablePermanent": { - "message": "Permanently", + "message": "कायमचे", "description": "English: Permanently" }, "docblockedDisable": { - "message": "Proceed", + "message": "पुढे जा", "description": "Button text to navigate to the blocked page" }, "docblockedRedirectPrompt": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "अवरोधित पृष्ठ दुसऱ्या साइटवर पुनर्निर्देशित करू इच्छित आहे. तुम्ही पुढे जाण्याचे निवडल्यास, तुम्ही थेट येथे नेव्हिगेट कराल: {{url}}", "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { - "message": "Reason:", + "message": "कारण:", "description": "The label which prepend the actual reason why a page was blocked" }, "docblockedReasonMalicious": { - "message": "Malicious", + "message": "दुर्भावनापूर्ण", "description": "An actual reason why a page was blocked" }, "docblockedReasonTracker": { - "message": "Tracker", + "message": "ट्रॅकर", "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { - "message": "Disreputable", + "message": "अप्रतिष्ठित", "description": "An actual reason why a page was blocked" }, "cloudPush": { - "message": "Export to cloud storage", + "message": "क्लाउड स्टोरेजमध्ये निर्यात करा", "description": "tooltip" }, "cloudPull": { - "message": "Import from cloud storage", + "message": "क्लाउड स्टोरेजमधून आयात करा", "description": "tooltip" }, "cloudPullAndMerge": { - "message": "Import from cloud storage and merge with current settings", + "message": "क्लाउड स्टोरेजमधून आयात करा आणि सध्याच्या सेटिंग्जमध्ये विलीन करा", "description": "tooltip" }, "cloudNoData": { @@ -1212,75 +1212,75 @@ "description": "" }, "cloudDeviceNamePrompt": { - "message": "This device name:", + "message": "या डिव्हाइसचे नाव:", "description": "used as a prompt for the user to provide a custom device name" }, "advancedSettingsWarning": { - "message": "Warning! Change these advanced settings at your own risk.", + "message": "सावधान! या प्रगत सेटिंग्ज स्वतःच्या जोखमीवर बदला.", "description": "A warning to users at the top of 'Advanced settings' page" }, "genericSubmit": { - "message": "Submit", + "message": "सबमिट करा", "description": "for generic 'Submit' buttons" }, "genericApplyChanges": { - "message": "Apply changes", + "message": "बदल लागू करा", "description": "for generic 'Apply changes' buttons" }, "genericRevert": { - "message": "Revert", + "message": "पूर्ववत करा", "description": "for generic 'Revert' buttons" }, "genericBytes": { - "message": "bytes", + "message": "बाइट्स", "description": "" }, "contextMenuBlockElementInFrame": { - "message": "Block element in frame…", + "message": "फ्रेममध्ये एलिमेंट अवरोधित करा…", "description": "An entry in the browser's contextual menu" }, "contextMenuSubscribeToList": { - "message": "Subscribe to filter list…", + "message": "फिल्टर यादीची सदस्यता घ्या…", "description": "An entry in the browser's contextual menu" }, "contextMenuTemporarilyAllowLargeMediaElements": { - "message": "Temporarily allow large media elements", + "message": "मोठे मीडिया एलिमेंट तात्पुरते अनुमती द्या", "description": "A context menu entry, present when large media elements have been blocked on the current site" }, "contextMenuViewSource": { - "message": "View source code…", + "message": "सोर्स कोड पहा…", "description": "A context menu entry, to view the source code of the target resource" }, "shortcutCapturePlaceholder": { - "message": "Type a shortcut", + "message": "शॉर्टकट टाइप करा", "description": "Placeholder string for input field used to capture a keyboard shortcut" }, "genericMergeViewScrollLock": { - "message": "Toggle locked scrolling", + "message": "लॉक केलेले स्क्रोलिंग टॉगल करा", "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" }, "genericCopyToClipboard": { - "message": "Copy to clipboard", + "message": "क्लिपबोर्डवर कॉपी करा", "description": "Label for buttons used to copy something to the clipboard" }, "genericSelectAll": { - "message": "Select all", + "message": "सर्व निवडा", "description": "Label for buttons used to select all text in editor" }, "toggleCosmeticFiltering": { - "message": "Toggle cosmetic filtering", + "message": "कॉस्मेटिक फिल्टरिंग टॉगल करा", "description": "Label for keyboard shortcut used to toggle cosmetic filtering" }, "toggleJavascript": { - "message": "Toggle JavaScript", + "message": "JavaScript टॉगल करा", "description": "Label for keyboard shortcut used to toggle no-scripting switch" }, "relaxBlockingMode": { - "message": "Relax blocking mode", + "message": "अवरोधन मोड शिथिल करा", "description": "Label for keyboard shortcut used to relax blocking mode" }, "storageUsed": { - "message": "Storage used: {{value}} {{unit}}", + "message": "वापरलेली स्टोरेज: {{value}} {{unit}}", "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" }, "KB": { @@ -1296,15 +1296,15 @@ "description": "short for 'gigabytes'" }, "clickToLoad": { - "message": "Click to load", + "message": "लोड करण्यासाठी क्लिक करा", "description": "Message used in frame placeholders" }, "linterMainReport": { - "message": "Errors: {{count}}", + "message": "त्रुटी: {{count}}", "description": "Summary of number of errors as reported by the linter " }, "unprocessedRequestTooltip": { - "message": "Could not filter properly at browser launch. Reload the page to ensure proper filtering.", + "message": "ब्राउझर सुरू करताना योग्यरित्या फिल्टर करू शकले नाही. योग्य फिल्टरिंग सुनिश्चित करण्यासाठी पृष्ठ पुन्हा लोड करा.", "description": "A warning which will appear in the popup panel if needed" }, "dummy": { diff --git a/src/_locales/ms/messages.json b/src/_locales/ms/messages.json index 63d311c05dbcb..8eeb24ae1d794 100644 --- a/src/_locales/ms/messages.json +++ b/src/_locales/ms/messages.json @@ -16,7 +16,7 @@ "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "Kekal", + "message": "Tinggal di sini", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Peraturan tempatan: lajur ini adalah untuk peraturan yang dikuatkuasakan untuk laman semasa sahaja.\nPeraturan tempatan menolak peraturan global.", + "message": "Peraturan tempatan: lajur ini adalah untuk peraturan yang dikuatkuasakan untuk laman semasa sahaja.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -480,7 +480,7 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "Domain perisian hasad", + "message": "Perlindungan perisian hasad, keselamatan", "description": "Filter lists section name" }, "3pGroupSocial": { @@ -1176,23 +1176,23 @@ "description": "Button text to navigate to the blocked page" }, "docblockedRedirectPrompt": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "Laman yang disekat ingin melencong ke laman lain. Jika anda memilih untuk meneruskan, anda akan terus melayari: {{url}}", "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { - "message": "Reason:", + "message": "Sebab:", "description": "The label which prepend the actual reason why a page was blocked" }, "docblockedReasonMalicious": { - "message": "Malicious", + "message": "Berniat jahat", "description": "An actual reason why a page was blocked" }, "docblockedReasonTracker": { - "message": "Tracker", + "message": "Penjejak", "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { - "message": "Disreputable", + "message": "Tidak dipercayai", "description": "An actual reason why a page was blocked" }, "cloudPush": { diff --git a/src/_locales/nb/messages.json b/src/_locales/nb/messages.json index da64d301aacdc..bc3db4927858e 100644 --- a/src/_locales/nb/messages.json +++ b/src/_locales/nb/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Lokale regler: Denne kolonnen er for regler som bare gjelder for det gjeldende nettstedet.\nLokale regler har prioritet foran globale regler.", + "message": "Lokale regler: Denne kolonnen er for regler som bare gjelder for det gjeldende nettstedet.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { diff --git a/src/_locales/nl/messages.json b/src/_locales/nl/messages.json index 6d19c6595e395..3449ed1747718 100644 --- a/src/_locales/nl/messages.json +++ b/src/_locales/nl/messages.json @@ -1144,7 +1144,7 @@ "description": "label to be used for the parameter-less URL: https://cloud.githubusercontent.com/assets/585534/9832014/bfb1b8f0-593b-11e5-8a27-fba472a5529a.png" }, "docblockedFoundIn": { - "message": "Gevonden in:", + "message": "Het filter is gevonden in:", "description": "English: List of filter list names follows" }, "docblockedBack": { diff --git a/src/_locales/oc/messages.json b/src/_locales/oc/messages.json index e5000b4eda483..738ea2cef837a 100644 --- a/src/_locales/oc/messages.json +++ b/src/_locales/oc/messages.json @@ -16,7 +16,7 @@ "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "Demorar", + "message": "Demorar aicí", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { @@ -68,7 +68,7 @@ "description": "Title for the advanced settings page" }, "popupPowerSwitchInfo": { - "message": "Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page.", + "message": "Clic: desactivar/activar uBlock₀ per aqueste site.\n\nCtrl+clic: desactivar uBlock₀ solament sus aquesta pagina.", "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." }, "popupPowerSwitchInfo1": { @@ -132,7 +132,7 @@ "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipNoPopups": { - "message": "Toggle the blocking of all popups for this site", + "message": "Activar/desactivar lo blocatge de totes las fenèstras sorgissents per aqueste site", "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoPopups1": { @@ -144,7 +144,7 @@ "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoLargeMedia": { - "message": "Toggle the blocking of large media elements for this site", + "message": "Activar/desactivar lo blocatge dels grands elements mèdia per aqueste site", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoLargeMedia1": { @@ -156,19 +156,19 @@ "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoCosmeticFiltering": { - "message": "Toggle cosmetic filtering for this site", + "message": "Activar/desactivar lo filtratge cosmetic per aqueste site", "description": "Tooltip for the no-cosmetic-filtering per-site switch" }, "popupTipNoCosmeticFiltering1": { - "message": "Click to disable cosmetic filtering on this site", + "message": "Clicatz per desactivar lo filtratge cosmetic sus aqueste site", "description": "Tooltip for the no-cosmetic-filtering per-site switch" }, "popupTipNoCosmeticFiltering2": { - "message": "Click to enable cosmetic filtering on this site", + "message": "Clicatz per activar lo filtratge cosmetic sus aqueste site", "description": "Tooltip for the no-cosmetic-filtering per-site switch" }, "popupTipNoRemoteFonts": { - "message": "Toggle the blocking of remote fonts for this site", + "message": "Activar/desactivar lo blocatge de las poliças distantas per aqueste site", "description": "Tooltip for the no-remote-fonts per-site switch" }, "popupTipNoRemoteFonts1": { @@ -216,19 +216,19 @@ "description": "Label to be used to hide popup panel sections" }, "popupTipGlobalRules": { - "message": "Global rules: this column is for rules which apply to all sites.", + "message": "Règlas globalas: aquesta colomna es pels règlas que s'aplican a totes los sites.", "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Local rules: this column is for rules which apply to the current site only.", + "message": "Règlas localas: aquesta colomna es pels règlas que s'aplican solament al site actual.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { - "message": "Click to make your changes permanent.", + "message": "Clicatz per far vòstres cambiaments permanents.", "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." }, "popupTipRevertRules": { - "message": "Click to revert your changes.", + "message": "Clicatz per anullar vòstres cambiaments.", "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." }, "popupAnyRulePrompt": { @@ -244,7 +244,7 @@ "description": "" }, "popup3pPassiveRulePrompt": { - "message": "3rd-party CSS/images", + "message": "CSS/imATGES de tresena partida", "description": "" }, "popupInlineScriptRulePrompt": { @@ -252,15 +252,15 @@ "description": "" }, "popup1pScriptRulePrompt": { - "message": "1st-party scripts", + "message": "Scripts de primièra partida", "description": "" }, "popup3pScriptRulePrompt": { - "message": "3rd-party scripts", + "message": "Scripts de tresena partida", "description": "" }, "popup3pFrameRulePrompt": { - "message": "3rd-party frames", + "message": "Quadres de tresena partida", "description": "" }, "popupHitDomainCountPrompt": { @@ -280,7 +280,7 @@ "description": "Appears as an option to filter out firewall rows" }, "popup3pFrameFilter": { - "message": "frame", + "message": "quadre", "description": "Appears as an option to filter out firewall rows" }, "pickerCreate": { @@ -308,7 +308,7 @@ "description": "English: Cosmetic filters" }, "pickerCosmeticFiltersHint": { - "message": "Click, Ctrl-click", + "message": "Clic, Ctrl-clic", "description": "English: Click, Ctrl-click" }, "pickerContextMenuEntry": { @@ -316,19 +316,19 @@ "description": "An entry in the browser's contextual menu" }, "settingsCollapseBlockedPrompt": { - "message": "Hide placeholders of blocked elements", + "message": "Amagar los emplaçaires dels elements blocats", "description": "English: Hide placeholders of blocked elements" }, "settingsIconBadgePrompt": { - "message": "Show the number of blocked requests on the icon", + "message": "Afichar lo nombre de requèstas blocadas sus l'icòna", "description": "English: Show the number of blocked requests on the icon" }, "settingsTooltipsPrompt": { - "message": "Disable tooltips", + "message": "Desactivar las etiquetas d'ajuda", "description": "A checkbox in the Settings pane" }, "settingsContextMenuPrompt": { - "message": "Make use of context menu where appropriate", + "message": "Utilizar lo menú contextual ont es pertinent", "description": "English: Make use of context menu where appropriate" }, "settingsColorBlindPrompt": { @@ -348,7 +348,7 @@ "description": "Label for checkbox to pick an accent color" }, "settingsCloudStorageEnabledPrompt": { - "message": "Enable cloud storage support", + "message": "Activar lo supòrt d'emmagazinatge en núvol", "description": "" }, "settingsAdvancedUserPrompt": { @@ -356,15 +356,15 @@ "description": "Checkbox to let user access advanced, technical features" }, "settingsPrefetchingDisabledPrompt": { - "message": "Disable pre-fetching (to prevent any connection for blocked network requests)", + "message": "Desactivar la preextraccion (per evitar tota connexion per de requèstas de ret blocadas)", "description": "English: " }, "settingsHyperlinkAuditingDisabledPrompt": { - "message": "Disable hyperlink auditing", + "message": "Desactivar l'audit dels iperligams", "description": "English: " }, "settingsWebRTCIPAddressHiddenPrompt": { - "message": "Prevent WebRTC from leaking local IP addresses", + "message": "Empachar WebRTC de divolgar las adreças IP localas", "description": "English: " }, "settingPerSiteSwitchGroup": { @@ -372,15 +372,15 @@ "description": "" }, "settingPerSiteSwitchGroupSynopsis": { - "message": "These default behaviors can be overridden on a per-site basis", + "message": "Aquestes comportaments per defaut pòdon èsser anullats site per site", "description": "" }, "settingsNoCosmeticFilteringPrompt": { - "message": "Disable cosmetic filtering", + "message": "Desactivar lo filtratge cosmetic", "description": "" }, "settingsNoLargeMediaPrompt": { - "message": "Block media elements larger than {{input}} KB", + "message": "Blocar los elements mèdia mai grands de {{input}} KB", "description": "" }, "settingsNoRemoteFontsPrompt": { @@ -392,11 +392,11 @@ "description": "The default state for the per-site no-scripting switch" }, "settingsNoCSPReportsPrompt": { - "message": "Block CSP reports", + "message": "Blocar los rapòrts CSP", "description": "background information: https://github.com/gorhill/uBlock/issues/3150" }, "settingsUncloakCnamePrompt": { - "message": "Uncloak canonical names", + "message": "Desvelar los noms canonics", "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" }, "settingsAdvanced": { @@ -404,7 +404,7 @@ "description": "Section for controlling advanced-user settings" }, "settingsAdvancedSynopsis": { - "message": "Features suitable only for technical users", + "message": "Foncionalitats adaptadas solament als utilizaires tecnicas", "description": "Description of section controlling advanced-user settings" }, "settingsAdvancedUserSettings": { @@ -420,11 +420,11 @@ "description": "English: Last backup:" }, "3pListsOfBlockedHostsPrompt": { - "message": "{{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:", + "message": "{{netFilterCount}} filtres ret + {{cosmeticFilterCount}} filtres cosmetics de:", "description": "Appears at the top of the _3rd-party filters_ pane" }, "3pListsOfBlockedHostsPerListStats": { - "message": "{{used}} used out of {{total}}", + "message": "{{used}} utilizats sus {{total}}", "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "3pAutoUpdatePrompt1": { @@ -440,23 +440,23 @@ "description": "A button in the in the _3rd-party filters_ pane" }, "3pParseAllABPHideFiltersPrompt1": { - "message": "Parse and enforce cosmetic filters", + "message": "Analisar e aplicar los filtres cosmetics", "description": "English: Parse and enforce Adblock+ element hiding filters." }, "3pParseAllABPHideFiltersInfo": { - "message": "Cosmetic filters serve to hide elements in a web page which are deemed to be a visual nuisance, and which can't be blocked by the network request-based filtering engines.", + "message": "Los filtres cosmetics servon per amagar los elements d'una pagina web considerats coma una nusença visuala, e que pòdon pas èsser blocats pels motors de filtratge basats sus las requèstas ret.", "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." }, "3pIgnoreGenericCosmeticFilters": { - "message": "Ignore generic cosmetic filters", + "message": "Ignorar los filtres cosmetics generics", "description": "This will cause uBO to ignore all generic cosmetic filters." }, "3pIgnoreGenericCosmeticFiltersInfo": { - "message": "Generic cosmetic filters are those cosmetic filters which are meant to apply on all web sites. Enabling this option will eliminate the memory and CPU overhead added to web pages as a result of handling generic cosmetic filters.\n\nIt is recommended to enable this option on less powerful devices.", + "message": "Los filtres cosmetics generics son aqueles filtres cosmetics que son destinats a s'aplicar sus totes los sites web. Activar aquesta opcion eliminarà lo subrecarg de memòria e de CPU apondut a las paginas web en resultant del tractament dels filtres cosmetics generics.\n\nEs recomandat d'activar aquesta opcion sus los dispositius mens poderoses.", "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." }, "3pSuspendUntilListsAreLoaded": { - "message": "Suspend network activity until all filter lists are loaded", + "message": "Suspendre l'activitat ret fins que totas las listas de filtres sián cargadas", "description": "A checkbox in the 'Filter lists' pane" }, "3pListsOfBlockedHostsHeader": { @@ -480,23 +480,23 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "Domenis malfasents", + "message": "Proteccion dels malware, seguretat", "description": "Filter lists section name" }, "3pGroupSocial": { - "message": "Social widgets", + "message": "Widgets socials", "description": "Filter lists section name" }, "3pGroupCookies": { - "message": "Cookie notices", + "message": "Anoncis de cookies", "description": "Filter lists section name" }, "3pGroupAnnoyances": { - "message": "Annoyances", + "message": "Nusenças", "description": "Filter lists section name" }, "3pGroupMultipurpose": { - "message": "Multipurpose", + "message": "Multipausa", "description": "Filter lists section name" }, "3pGroupRegions": { @@ -512,7 +512,7 @@ "description": "The label for the checkbox used to import external filter lists" }, "3pExternalListsHint": { - "message": "One URL per line. Invalid URLs will be silently ignored.", + "message": "Un URL per linha. Los URLs invalidas seràn ignoradas silenciosament.", "description": "Short information about how to use the textarea to import external filter lists by URL" }, "3pExternalListObsolete": { @@ -532,19 +532,19 @@ "description": "used as a tooltip for the spinner icon beside a list" }, "3pNetworkError": { - "message": "A network error prevented the resource from being updated.", + "message": "Una error ret a empachat la mesa a jorn de la ressorsa.", "description": "used as a tooltip for error icon beside a list" }, "1pTrustWarning": { - "message": "Do not add filters from untrusted sources.", + "message": "Non apondre de filtres de fonts pas fisablas.", "description": "Warning against copy-pasting filters from random sources" }, "1pEnableMyFiltersLabel": { - "message": "Enable my custom filters", + "message": "Activar mos filtres personalizats", "description": "Label for the checkbox use to enable/disable 'My filters' list" }, "1pTrustMyFiltersLabel": { - "message": "Allow custom filters requiring trust", + "message": "Permetre los filtres personalizats que requerisson fisança", "description": "Label for the checkbox use to trust the content of 'My filters' list" }, "1pImport": { @@ -572,11 +572,11 @@ "description": "header" }, "rulesRevert": { - "message": "Revert", + "message": "Anullar", "description": "This will remove all temporary rules" }, "rulesCommit": { - "message": "Commit", + "message": "Validar", "description": "This will persist temporary rules" }, "rulesEdit": { @@ -592,11 +592,11 @@ "description": "Will discard manually-edited content and exit manual-edit mode" }, "rulesImport": { - "message": "Import from file…", + "message": "Importar dempuèi un fichièr…", "description": "" }, "rulesExport": { - "message": "Export to file…", + "message": "Exportar cap a un fichièr…", "description": "Button in the 'My rules' pane" }, "rulesDefaultFileName": { @@ -604,11 +604,11 @@ "description": "default file name to use" }, "rulesHint": { - "message": "List of your dynamic filtering rules.", + "message": "Lista de vòstres règlas de filtratge dinamics.", "description": "English: List of your dynamic filtering rules." }, "rulesFormatHint": { - "message": "Rule syntax: source destination type action (full documentation).", + "message": "Sintaxi de la règlas: font destinacion tipe accion (documentacion completa).", "description": "English: dynamic rule syntax and full documentation." }, "rulesSort": { @@ -628,11 +628,11 @@ "description": "English: a sort option for list of rules." }, "whitelistPrompt": { - "message": "The trusted site directives dictate on which web pages uBlock Origin should be disabled. One entry per line.", + "message": "Las directivas dels sites fisables indican sus qualas paginas web uBlock Origin deu èsser desactivat. Una entrada per linha.", "description": "A concise description of the 'Trusted sites' pane." }, "whitelistImport": { - "message": "Import and append…", + "message": "Importar e apondre…", "description": "Button in the 'Trusted sites' pane" }, "whitelistExport": { @@ -668,7 +668,7 @@ "description": "Appears in the logger's tab selector" }, "logBehindTheScene": { - "message": "Tabless", + "message": "Sens onglet", "description": "Pretty name for behind-the-scene network requests" }, "loggerCurrentTab": { @@ -676,47 +676,47 @@ "description": "Appears in the logger's tab selector" }, "loggerReloadTip": { - "message": "Reload the tab content", + "message": "Recargar lo contengut de l'onglet", "description": "Tooltip for the reload button in the logger page" }, "loggerDomInspectorTip": { - "message": "Toggle the DOM inspector", + "message": "Activar/desactivar l'inspector DOM", "description": "Tooltip for the DOM inspector button in the logger page" }, "loggerPopupPanelTip": { - "message": "Toggle the popup panel", + "message": "Activar/desactivar lo panèl sorgissent", "description": "Tooltip for the popup panel button in the logger page" }, "loggerInfoTip": { - "message": "uBlock Origin wiki: The logger", + "message": "Wiki uBlock Origin: Lo registre", "description": "Tooltip for the top-right info label in the logger page" }, "loggerClearTip": { - "message": "Clear logger", + "message": "Escafar lo registre", "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" }, "loggerPauseTip": { - "message": "Pause logger (discard all incoming data)", + "message": "Pausar lo registre (regetar totas las donadas entrantas)", "description": "Tooltip for the pause button in the logger page" }, "loggerUnpauseTip": { - "message": "Unpause logger", + "message": "Repausar lo registre", "description": "Tooltip for the play button in the logger page" }, "loggerRowFiltererButtonTip": { - "message": "Toggle logger filtering", + "message": "Activar/desactivar lo filtratge del registre", "description": "Tooltip for the row filterer button in the logger page" }, "logFilterPrompt": { - "message": "filter logger content", + "message": "filtrar lo contengut del registre", "description": "Placeholder string for logger output filtering input field" }, "loggerRowFiltererBuiltinTip": { - "message": "Logger filtering options", + "message": "Opcions de filtratge del registre", "description": "Tooltip for the button to bring up logger output filtering options" }, "loggerRowFiltererBuiltinNot": { - "message": "Not", + "message": "Pas", "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltinEventful": { @@ -736,11 +736,11 @@ "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltin1p": { - "message": "1st-party", + "message": "Primièra partida", "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltin3p": { - "message": "3rd-party", + "message": "Tresena partida", "description": "A keyword in the built-in row filtering expression" }, "loggerEntryDetailsHeader": { @@ -764,11 +764,11 @@ "description": "Label to identify a context field (typically a hostname)" }, "loggerEntryDetailsRootContext": { - "message": "Root context", + "message": "Contèxte racin", "description": "Label to identify a root context field (typically a hostname)" }, "loggerEntryDetailsPartyness": { - "message": "Partyness", + "message": "Partida", "description": "Label to identify a field providing partyness information" }, "loggerEntryDetailsType": { @@ -792,11 +792,11 @@ "description": "Label for the type selector" }, "loggerStaticFilteringHeader": { - "message": "Static filter", + "message": "Filtre estatic", "description": "Small header to identify the static filtering section" }, "loggerStaticFilteringSentence": { - "message": "{{action}} network requests of {{type}} {{br}}which URL address matches {{url}} {{br}}and which originates {{origin}},{{br}}{{importance}} there is a matching exception filter.", + "message": "{{action}} las requèstas ret de {{type}} {{br}}que l'adreça URL correspond a {{url}} {{br}}e que provenon de {{origin}},{{br}}{{importance}} i a un filtre d'excepcion correspondent.", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartBlock": { @@ -808,75 +808,75 @@ "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartType": { - "message": "type “{{type}}”", + "message": "tipe “{{type}}”", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartAnyType": { - "message": "any type", + "message": "qualque tipe", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartOrigin": { - "message": "from “{{origin}}”", + "message": "de “{{origin}}”", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartAnyOrigin": { - "message": "from anywhere", + "message": "de pertot", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartNotImportant": { - "message": "except when", + "message": "levat quand", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartImportant": { - "message": "even if", + "message": "quitament se", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringFinderSentence1": { - "message": "Static filter {{filter}} found in:", + "message": "Filtre estatic {{filter}} trobat dins:", "description": "Below this sentence, the filter list(s) in which the filter was found" }, "loggerStaticFilteringFinderSentence2": { - "message": "Static filter could not be found in any of the currently enabled filter lists", + "message": "Lo filtre estatic a pas pogut èsser trobat dins cap de las listas de filtres actualament activadas", "description": "Message to show when a filter cannot be found in any filter lists" }, "loggerSettingDiscardPrompt": { - "message": "Logger entries which do not fulfill all three conditions below will be automatically discarded:", + "message": "Las entradas del registre que complisson pas las tres condicions çai-jos seràn automaticament regetadas:", "description": "Logger setting: A sentence to describe the purpose of the settings below" }, "loggerSettingPerEntryMaxAge": { - "message": "Preserve entries from the last {{input}} minutes", + "message": "Conservar las entradas dels darrièrs {{input}} minutas", "description": "A logger setting" }, "loggerSettingPerTabMaxLoads": { - "message": "Preserve at most {{input}} page loads per tab", + "message": "Conservar al maximum {{input}} cargaments de pagina per onglet", "description": "A logger setting" }, "loggerSettingPerTabMaxEntries": { - "message": "Preserve at most {{input}} entries per tab", + "message": "Conservar al maximum {{input}} entradas per onglet", "description": "A logger setting" }, "loggerSettingPerEntryLineCount": { - "message": "Use {{input}} lines per entry in vertically expanded mode", + "message": "Utilizar {{input}} linhas per entrada en mòde verticalament espandit", "description": "A logger setting" }, "loggerSettingHideColumnsPrompt": { - "message": "Hide columns:", + "message": "Amagar las colomnas:", "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" }, "loggerSettingHideColumnTime": { - "message": "{{input}} Time", + "message": "{{input}} Ora", "description": "A label for the time column" }, "loggerSettingHideColumnFilter": { - "message": "{{input}} Filter/rule", + "message": "{{input}} Filtre/règla", "description": "A label for the filter or rule column" }, "loggerSettingHideColumnContext": { - "message": "{{input}} Context", + "message": "{{input}} Contèxte", "description": "A label for the context column" }, "loggerSettingHideColumnPartyness": { - "message": "{{input}} Partyness", + "message": "{{input}} Partida", "description": "A label for the partyness column" }, "loggerExportFormatList": { @@ -900,11 +900,11 @@ "description": "Text for button which open an external web page in Support pane" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "Crear un novèl rapòrt sus GitHub", "description": "Text for button which open an external web page in Support pane" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "Trobar de rapòrts semblables sus GitHub", "description": "A clickable link in the filter issue reporter section" }, "supportS1H": { @@ -912,31 +912,31 @@ "description": "Header of 'Documentation' section in Support pane" }, "supportS1P1": { - "message": "Read the documentation at uBlock/wiki to learn about all of uBlock Origin's features.", + "message": "Legir la documentacion sus uBlock/wiki per aprene totas las foncionalitats d'uBlock Origin.", "description": "First paragraph of 'Documentation' section in Support pane" }, "supportS2H": { - "message": "Questions and support", + "message": "Questions e supòrt", "description": "Header of 'Questions and support' section in Support pane" }, "supportS2P1": { - "message": "Answers to questions and other kinds of help support is provided on the subreddit /r/uBlockOrigin.", + "message": "Las responsas a las questions e los autres tipes d'ajuda son provesits sul subreddit /r/uBlockOrigin.", "description": "First paragraph of 'Questions and support' section in Support pane" }, "supportS3H": { - "message": "Filter issues/website is broken", + "message": "Problemas de filtres / site web romput", "description": "Header of 'Filter issues' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "Senhalar los problemas de filtres amb de sites web especifics al seguidor de problèmas uBlockOrigin/uAssets. Require un compte GitHub.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS3P2": { - "message": "Important: Avoid using other similarly-purposed blockers along with uBlock Origin, as this may cause filter issues on specific websites.", + "message": "Important: Evitar d'utilizar d'autres blocaires amb de finalitats similaras amb uBlock Origin, que aquò pòt causar de problèmas de filtres sus de sites web especifics.", "description": "Second paragraph of 'Filter issues' section in Support pane" }, "supportS3P3": { - "message": "Tips: Be sure your filter lists are up to date. The logger is the primary tool to diagnose filter-related issues.", + "message": "Conseills: Assegurar-vos que vòstras listas de filtres son a jorn. Lo registre es l'esplech principal per diagnosticar los problèmas ligats als filtres.", "description": "Third paragraph of 'Filter issues' section in Support pane" }, "supportS4H": { @@ -944,75 +944,75 @@ "description": "Header of 'Bug report' section in Support pane" }, "supportS4P1": { - "message": "Report issues with uBlock Origin itself to the uBlockOrigin/uBlock-issue issue tracker. Requires a GitHub account.", + "message": "Senhalar los problèmas amb uBlock Origin meteis al seguidor de problèmas uBlockOrigin/uBlock-issue. Require un compte GitHub.", "description": "First paragraph of 'Bug report' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting Information", + "message": "Informacions de diagnostic", "description": "Header of 'Troubleshooting Information' section in Support pane" }, "supportS5P1": { - "message": "Below is technical information that might be useful when volunteers are trying to help you solve a problem.", + "message": "Çai-jos se tròba d'informacions tecnicas que pòdon èsser utilas quand los volontaris ensajan de vos ajudar a resòlvre un problèma.", "description": "First paragraph of 'Troubleshooting Information' section in Support pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "Senhalar un problèma de filtre", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "Per evitar de cargar los volontaris amb de rapòrts dobles, verificatz que lo problèma a pas ja estat senhalat. Nòta: clicar sul boton enviarà l'origina de la pagina a GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { - "message": "Filter lists are updated daily. Be sure your issue has not already been addressed in the most recent filter lists.", + "message": "Las listas de filtres son mesas a jorn quotidianament. Asseguratz-vos que vòstre problèma es pas estat ja tractat dins las listas de filtres mai recentas.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S2": { - "message": "Verify that the issue still exists after reloading the problematic web page.", + "message": "Verificatz que lo problèma existís totjorn aprèp aver recargat la pagina web problematic.", "description": "A paragraph in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "Adreça de la pagina web:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "La pagina web…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- Causir una entrada --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "Aficha de publicitats o de rèstas de publicitat", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "A de subrecobriments o d'autras nusenças", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBlock Origin", + "message": "Detecta uBlock Origin", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "A de problèmas ligats a la confidencialitat", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBlock Origin is enabled", + "message": "Malaise quand uBlock Origin es activat", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "Dobrís d'onglets o de fenèstras pas desirats", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "Mena a de logicials malhèsts, phishing", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "Marcar la pagina web coma “NSFW” (“Pas segur pel trabalh”)", "description": "A checkbox to use for NSFW sites" }, "aboutPrivacyPolicy": { @@ -1044,19 +1044,19 @@ "description": "Link text to uBO's own filter lists repo" }, "aboutDependencies": { - "message": "External dependencies (GPLv3-compatible):", + "message": "Dependéncias extèrnas (compatiblas GPLv3):", "description": "Shown in the About pane" }, "aboutCDNs": { - "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "message": "Las pròprias listas de filtres d'uBO son albergadas gratuitament sus los CDN seguents:", "description": "Shown in the About pane" }, "aboutCDNsInfo": { - "message": "A randomly picked CDN is used when a filter list needs to be updated.", + "message": "Un CDN causit aleatòriament es utilizat quand una lista de filtres deu èsser mesa a jorn.", "description": "Shown in the About pane" }, "aboutBackupDataButton": { - "message": "Back up to file…", + "message": "Salvar dins un fichièr…", "description": "Text for button to create a backup of all settings" }, "aboutBackupFilename": { @@ -1064,27 +1064,27 @@ "description": "English: my-ublock-backup_{{datetime}}.txt" }, "aboutRestoreDataButton": { - "message": "Restore from file…", + "message": "Restaurar dempuèi un fichièr…", "description": "English: Restore from file..." }, "aboutResetDataButton": { - "message": "Reset to default settings…", + "message": "Reïnicializar als paramètres per defaut…", "description": "English: Reset to default settings..." }, "aboutRestoreDataConfirm": { - "message": "All your settings will be overwritten using data backed up on {{time}}, and uBlock₀ will restart.\n\nOverwrite all existing settings using backed up data?", + "message": "Totes vòstres paramètres seràn subrescrits amb las donadas salvadas lo {{time}}, e uBlock₀ se reaviarà.\n\nSubrescríser totes los paramètres existents amb las donadas salvadas ?", "description": "Message asking user to confirm restore" }, "aboutRestoreDataError": { - "message": "The data could not be read or is invalid", + "message": "Las donadas an pas pogut èsser legidas o son invalidas", "description": "Message to display when an error occurred during restore" }, "aboutResetDataConfirm": { - "message": "All your settings will be removed, and uBlock₀ will restart.\n\nReset uBlock₀ to factory settings?", + "message": "Totes vòstres paramètres seràn suprimits, e uBlock₀ se reaviarà.\n\nReïnicializar uBlock₀ als paramètres d'usina ?", "description": "Message asking user to confirm reset" }, "errorCantConnectTo": { - "message": "Network error: {{msg}}", + "message": "Error ret: {{msg}}", "description": "English: Network error: {{msg}}" }, "subscribeButton": { @@ -1116,15 +1116,15 @@ "description": "English: {{value}} days ago" }, "showDashboardButton": { - "message": "Show Dashboard", + "message": "Afichar lo Tablèu de bòrd", "description": "Firefox/Fennec-specific: Show Dashboard" }, "showNetworkLogButton": { - "message": "Show Logger", + "message": "Afichar lo registre", "description": "Firefox/Fennec-specific: Show Logger" }, "fennecMenuItemBlockingOff": { - "message": "off", + "message": "desactivat", "description": "Firefox-specific: appears as 'uBlock₀ (off)'" }, "docblockedTitle": { @@ -1140,7 +1140,7 @@ "description": "Used in the strict-blocking page" }, "docblockedNoParamsPrompt": { - "message": "without parameters", + "message": "sens paramètres", "description": "label to be used for the parameter-less URL: https://cloud.githubusercontent.com/assets/585534/9832014/bfb1b8f0-593b-11e5-8a27-fba472a5529a.png" }, "docblockedFoundIn": { @@ -1180,11 +1180,11 @@ "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { - "message": "Reason:", + "message": "Rason:", "description": "The label which prepend the actual reason why a page was blocked" }, "docblockedReasonMalicious": { - "message": "Malicious", + "message": "Malvolent", "description": "An actual reason why a page was blocked" }, "docblockedReasonTracker": { @@ -1192,19 +1192,19 @@ "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { - "message": "Disreputable", + "message": "De mal reputacion", "description": "An actual reason why a page was blocked" }, "cloudPush": { - "message": "Export to cloud storage", + "message": "Exportar cap a l'emmagazinatge en núvol", "description": "tooltip" }, "cloudPull": { - "message": "Import from cloud storage", + "message": "Importar dempuèi l'emmagazinatge en núvol", "description": "tooltip" }, "cloudPullAndMerge": { - "message": "Import from cloud storage and merge with current settings", + "message": "Importar dempuèi l'emmagazinatge en núvol e fusionar amb los paramètres actuals", "description": "tooltip" }, "cloudNoData": { @@ -1216,7 +1216,7 @@ "description": "used as a prompt for the user to provide a custom device name" }, "advancedSettingsWarning": { - "message": "Warning! Change these advanced settings at your own risk.", + "message": "Avertiment ! Cambiar aquestes paramètres avançats a vòstre risc.", "description": "A warning to users at the top of 'Advanced settings' page" }, "genericSubmit": { @@ -1236,11 +1236,11 @@ "description": "" }, "contextMenuBlockElementInFrame": { - "message": "Block element in frame…", + "message": "Blocar l'element dins lo quadre…", "description": "An entry in the browser's contextual menu" }, "contextMenuSubscribeToList": { - "message": "Subscribe to filter list…", + "message": "Abonar a la lista de filtres…", "description": "An entry in the browser's contextual menu" }, "contextMenuTemporarilyAllowLargeMediaElements": { @@ -1248,7 +1248,7 @@ "description": "A context menu entry, present when large media elements have been blocked on the current site" }, "contextMenuViewSource": { - "message": "View source code…", + "message": "Veire lo còdi font…", "description": "A context menu entry, to view the source code of the target resource" }, "shortcutCapturePlaceholder": { @@ -1256,7 +1256,7 @@ "description": "Placeholder string for input field used to capture a keyboard shortcut" }, "genericMergeViewScrollLock": { - "message": "Toggle locked scrolling", + "message": "Activar/desactivar lo scroll blocat", "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" }, "genericCopyToClipboard": { @@ -1268,15 +1268,15 @@ "description": "Label for buttons used to select all text in editor" }, "toggleCosmeticFiltering": { - "message": "Toggle cosmetic filtering", + "message": "Activar/desactivar lo filtratge cosmetic", "description": "Label for keyboard shortcut used to toggle cosmetic filtering" }, "toggleJavascript": { - "message": "Toggle JavaScript", + "message": "Activar/desactivar JavaScript", "description": "Label for keyboard shortcut used to toggle no-scripting switch" }, "relaxBlockingMode": { - "message": "Relax blocking mode", + "message": "Alèujar lo mòde de blocatge", "description": "Label for keyboard shortcut used to relax blocking mode" }, "storageUsed": { @@ -1304,7 +1304,7 @@ "description": "Summary of number of errors as reported by the linter " }, "unprocessedRequestTooltip": { - "message": "Could not filter properly at browser launch. Reload the page to ensure proper filtering.", + "message": "Filtratge impossible corrèctament al lançament del navigador. Recargatz la pagina per assegurar un filtratge corrècte.", "description": "A warning which will appear in the popup panel if needed" }, "dummy": { diff --git a/src/_locales/pa/messages.json b/src/_locales/pa/messages.json index 3f3abba147e9c..ba07ca5fa3b50 100644 --- a/src/_locales/pa/messages.json +++ b/src/_locales/pa/messages.json @@ -16,7 +16,7 @@ "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "ਰਹੋ", + "message": "ਇੱਥੇ ਰਹੋ", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { @@ -116,11 +116,11 @@ "description": "English: Click to open the dashboard" }, "popupTipZapper": { - "message": "Enter element zapper mode", + "message": "ਤੱਤ ਜੈਪਰ ਮੋਡ ਵਿੱਚ ਦਾਖਲ ਹੋਵੋ", "description": "Tooltip for the element-zapper icon in the popup panel" }, "popupTipPicker": { - "message": "Enter element picker mode", + "message": "ਤੱਤ ਚੁਣਨ ਵਾਲਾ ਮੋਡ ਵਿੱਚ ਦਾਖਲ ਹੋਵੋ", "description": "English: Enter element picker mode" }, "popupTipLog": { @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "ਲੋਕਲ ਨਿਯਮ: ਇਹ ਕਾਲਮ ਨਿਯਮਾਂ ਲਈ ਹੈ, ਜੋ ਕਿ ਸਿਰਫ਼ ਲੋਕਲ ਸਾਈਟਾਂ ਉੱਤੇ ਹੀ ਲਾਗੂ ਹੁੰਦੇ ਹਨ।\nਲੋਕਲ ਨਿਯਮ ਗਲੋਬਲ ਨਿਯਮਾਂ ਨੂੰ ਅਣਡਿੱਠਾ ਕਰਦੇ ਹਨ।", + "message": "ਲੋਕਲ ਨਿਯਮ: ਇਹ ਕਾਲਮ ਨਿਯਮਾਂ ਲਈ ਹੈ, ਜੋ ਕਿ ਸਿਰਫ਼ ਲੋਕਲ ਸਾਈਟਾਂ ਉੱਤੇ ਹੀ ਲਾਗੂ ਹੁੰਦੇ ਹਨ।", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -344,7 +344,7 @@ "description": "Label for checkbox to enable a custom dark theme" }, "settingsThemeAccent0Label": { - "message": "Custom accent color", + "message": "ਕਸਟਮ ਐਕਸੈਂਟ ਰੰਗ", "description": "Label for checkbox to pick an accent color" }, "settingsCloudStorageEnabledPrompt": { @@ -396,7 +396,7 @@ "description": "background information: https://github.com/gorhill/uBlock/issues/3150" }, "settingsUncloakCnamePrompt": { - "message": "Uncloak canonical names", + "message": "ਕੈਨੋਨੀਕਲ ਨਾਮ ਅਣਛੁਪਾਓ", "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" }, "settingsAdvanced": { @@ -452,7 +452,7 @@ "description": "This will cause uBO to ignore all generic cosmetic filters." }, "3pIgnoreGenericCosmeticFiltersInfo": { - "message": "Generic cosmetic filters are those cosmetic filters which are meant to apply on all web sites. Enabling this option will eliminate the memory and CPU overhead added to web pages as a result of handling generic cosmetic filters.\n\nIt is recommended to enable this option on less powerful devices.", + "message": "ਆਮ ਕਾਸਮੈਟਿਕ ਫਿਲਟਰ ਉਹ ਕਾਸਮੈਟਿਕ ਫਿਲਟਰ ਹਨ ਜੋ ਸਾਰੀਆਂ ਵੈੱਬ ਸਾਈਟਾਂ 'ਤੇ ਲਾਗੂ ਹੋਣ ਦੇ ਇਰਾਦੇ ਨਾਲ ਹੁੰਦੇ ਹਨ। ਇਸ ਵਿਕਲਪ ਨੂੰ ਸਮਰੱਥ ਬਣਾਉਣ ਨਾਲ ਆਮ ਕਾਸਮੈਟਿਕ ਫਿਲਟਰਾਂ ਦੀ ਪ੍ਰਕਿਰਿਆ ਦੇ ਨਤੀਜੇ ਵਜੋਂ ਵੈੱਬ ਪੰਨਿਆਂ ਵਿੱਚ ਜੋੜੇ ਗਏ ਮੈਮਰੀ ਅਤੇ CPU ਓਵਰਹੈੱਡ ਨੂੰ ਖਤਮ ਕਰ ਦਿੱਤਾ ਜਾਵੇਗਾ।\n\nਘੱਟ ਸਮਰੱਥਾ ਵਾਲੇ ਡਿਵਾਈਸਾਂ 'ਤੇ ਇਸ ਵਿਕਲਪ ਨੂੰ ਸਮਰੱਥ ਕਰਨ ਦੀ ਸਿਫ਼ਾਰਸ਼ ਕੀਤੀ ਜਾਂਦੀ ਹੈ।", "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." }, "3pSuspendUntilListsAreLoaded": { @@ -544,7 +544,7 @@ "description": "Label for the checkbox use to enable/disable 'My filters' list" }, "1pTrustMyFiltersLabel": { - "message": "Allow custom filters requiring trust", + "message": "ਭਰੋਸੇ ਦੀ ਲੋੜ ਵਾਲੇ ਕਸਟਮ ਫਿਲਟਰਾਂ ਨੂੰ ਆਗਿਆ ਦਿਓ", "description": "Label for the checkbox use to trust the content of 'My filters' list" }, "1pImport": { @@ -608,7 +608,7 @@ "description": "English: List of your dynamic filtering rules." }, "rulesFormatHint": { - "message": "Rule syntax: source destination type action (full documentation).", + "message": "ਨਿਯਮ ਸੰਟੈਕਸ: ਸਰੋਤ ਮੰਜ਼ਿਲ ਕਿਸਮ ਕਿਰਿਆ (ਪੂਰੀ ਦਸਤਾਵੇਜ਼ੀ).", "description": "English: dynamic rule syntax and full documentation." }, "rulesSort": { @@ -628,7 +628,7 @@ "description": "English: a sort option for list of rules." }, "whitelistPrompt": { - "message": "The trusted site directives dictate on which web pages uBlock Origin should be disabled. One entry per line.", + "message": "ਭਰੋਸੇਯੋਗ ਸਾਈਟ ਨਿਰਦੇਸ਼ ਇਹ ਦੱਸਦੇ ਹਨ ਕਿ ਕਿਹੜੀਆਂ ਵੈੱਬ ਪੰਨਿਆਂ 'ਤੇ uBlock Origin ਨੂੰ ਅਸਮਰੱਥ ਕੀਤਾ ਜਾਣਾ ਚਾਹੀਦਾ ਹੈ। ਇੱਕ ਲਾਈਨ ਵਿੱਚ ਇੱਕ ਐਂਟਰੀ।", "description": "A concise description of the 'Trusted sites' pane." }, "whitelistImport": { @@ -796,7 +796,7 @@ "description": "Small header to identify the static filtering section" }, "loggerStaticFilteringSentence": { - "message": "{{action}} network requests of {{type}} {{br}}which URL address matches {{url}} {{br}}and which originates {{origin}},{{br}}{{importance}} there is a matching exception filter.", + "message": "{{action}} {{type}} ਦੇ ਨੈੱਟਵਰਕ ਬੇਨਤੀਆਂ {{br}}ਜਿਨ੍ਹਾਂ ਦਾ URL ਪਤਾ {{url}} ਨਾਲ ਮੇਲ ਖਾਂਦਾ ਹੈ {{br}}ਅਤੇ ਜੋ {{origin}} ਤੋਂ ਉਤਪੰਨ ਹੁੰਦੀਆਂ ਹਨ,{{br}}{{importance}} ਇੱਕ ਮੇਲ ਖਾਂਦਾ ਅਪਵਾਦ ਫਿਲਟਰ ਮੌਜੂਦ ਹੈ।", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartBlock": { @@ -836,11 +836,11 @@ "description": "Below this sentence, the filter list(s) in which the filter was found" }, "loggerStaticFilteringFinderSentence2": { - "message": "Static filter could not be found in any of the currently enabled filter lists", + "message": "ਸਥਿਰ ਫਿਲਟਰ ਮੌਜੂਦਾ ਸਮਰੱਥ ਫਿਲਟਰ ਸੂਚੀਆਂ ਵਿੱਚੋਂ ਕਿਸੇ ਵਿੱਚ ਨਹੀਂ ਮਿਲ ਸਕਿਆ", "description": "Message to show when a filter cannot be found in any filter lists" }, "loggerSettingDiscardPrompt": { - "message": "Logger entries which do not fulfill all three conditions below will be automatically discarded:", + "message": "ਲੌਗਰ ਐਂਟਰੀਆਂ ਜੋ ਹੇਠਾਂ ਦਿੱਤੀਆਂ ਸਾਰੀਆਂ ਤਿੰਨ ਸ਼ਰਤਾਂ ਪੂਰੀਆਂ ਨਹੀਂ ਕਰਦੀਆਂ, ਆਪਣੇ ਆਪ ਰੱਦ ਕਰ ਦਿੱਤੀਆਂ ਜਾਣਗੀਆਂ:", "description": "Logger setting: A sentence to describe the purpose of the settings below" }, "loggerSettingPerEntryMaxAge": { @@ -848,15 +848,15 @@ "description": "A logger setting" }, "loggerSettingPerTabMaxLoads": { - "message": "Preserve at most {{input}} page loads per tab", + "message": "ਪ੍ਰਤੀ ਟੈਬ ਵੱਧ ਤੋਂ ਵੱਧ {{input}} ਪੰਨਾ ਲੋਡ ਸੁਰੱਖਿਅਤ ਰੱਖੋ", "description": "A logger setting" }, "loggerSettingPerTabMaxEntries": { - "message": "Preserve at most {{input}} entries per tab", + "message": "ਪ੍ਰਤੀ ਟੈਬ ਵੱਧ ਤੋਂ ਵੱਧ {{input}} ਐਂਟਰੀਆਂ ਸੁਰੱਖਿਅਤ ਰੱਖੋ", "description": "A logger setting" }, "loggerSettingPerEntryLineCount": { - "message": "Use {{input}} lines per entry in vertically expanded mode", + "message": "ਲੰਬਕਾਰੀ ਵਿਸਤ੍ਰਿਤ ਮੋਡ ਵਿੱਚ ਪ੍ਰਤੀ ਐਂਟਰੀ {{input}} ਲਾਈਨਾਂ ਵਰਤੋ", "description": "A logger setting" }, "loggerSettingHideColumnsPrompt": { @@ -928,15 +928,15 @@ "description": "Header of 'Filter issues' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "ਖਾਸ ਵੈੱਬਸਾਈਟਾਂ ਨਾਲ ਫਿਲਟਰ ਸਮੱਸਿਆਵਾਂ ਦੀ ਰਿਪੋਰਟ uBlockOrigin/uAssets ਇਸ਼ੂ ਟਰੈਕਰ ਨੂੰ ਕਰੋ। ਇੱਕ GitHub ਖਾਤੇ ਦੀ ਲੋੜ ਹੈ।", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS3P2": { - "message": "Important: Avoid using other similarly-purposed blockers along with uBlock Origin, as this may cause filter issues on specific websites.", + "message": "ਮਹੱਤਵਪੂਰਨ: uBlock Origin ਦੇ ਨਾਲ ਹੋਰ ਸਮਾਨ-ਉਦੇਸ਼ ਵਾਲੇ ਬਲੌਕਰਾਂ ਦੀ ਵਰਤੋਂ ਕਰਨ ਤੋਂ ਬਚੋ, ਕਿਉਂਕਿ ਇਸ ਨਾਲ ਖਾਸ ਵੈੱਬਸਾਈਟਾਂ 'ਤੇ ਫਿਲਟਰ ਸਮੱਸਿਆਵਾਂ ਹੋ ਸਕਦੀਆਂ ਹਨ।", "description": "Second paragraph of 'Filter issues' section in Support pane" }, "supportS3P3": { - "message": "Tips: Be sure your filter lists are up to date. The logger is the primary tool to diagnose filter-related issues.", + "message": "ਸੁਝਾਅ: ਯਕੀਨੀ ਬਣਾਓ ਕਿ ਤੁਹਾਡੀਆਂ ਫਿਲਟਰ ਸੂਚੀਆਂ ਅੱਪ-ਟੂ-ਡੇਟ ਹਨ। ਲੌਗਰ ਫਿਲਟਰ-ਸਬੰਧਤ ਸਮੱਸਿਆਵਾਂ ਦਾ ਪਤਾ ਲਗਾਉਣ ਲਈ ਮੁੱਖ ਸਾਧਨ ਹੈ।", "description": "Third paragraph of 'Filter issues' section in Support pane" }, "supportS4H": { @@ -944,7 +944,7 @@ "description": "Header of 'Bug report' section in Support pane" }, "supportS4P1": { - "message": "Report issues with uBlock Origin itself to the uBlockOrigin/uBlock-issue issue tracker. Requires a GitHub account.", + "message": "uBlock Origin ਨਾਲ ਸਬੰਧਤ ਸਮੱਸਿਆਵਾਂ ਦੀ ਰਿਪੋਰਟ uBlockOrigin/uBlock-issue ਇਸ਼ੂ ਟਰੈਕਰ ਨੂੰ ਕਰੋ। ਇੱਕ GitHub ਖਾਤੇ ਦੀ ਲੋੜ ਹੈ।", "description": "First paragraph of 'Bug report' section in Support pane" }, "supportS5H": { @@ -988,7 +988,7 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "ਓਵਰਲੇ ਜਾਂ ਹੋਰ ਪਰੇਸ਼ਾਨੀਆਂ ਹਨ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { @@ -1008,11 +1008,11 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "ਬੈਡਵੇਅਰ, ਫਿਸ਼ਿੰਗ ਵੱਲ ਲੈ ਜਾਂਦਾ ਹੈ", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "ਵੈੱਬ ਪੰਨੇ ਨੂੰ “NSFW” ਵਜੋਂ ਲੇਬਲ ਕਰੋ (“ਕੰਮ ਲਈ ਸੁਰੱਖਿਅਤ ਨਹੀਂ”)", "description": "A checkbox to use for NSFW sites" }, "aboutPrivacyPolicy": { @@ -1052,7 +1052,7 @@ "description": "Shown in the About pane" }, "aboutCDNsInfo": { - "message": "A randomly picked CDN is used when a filter list needs to be updated.", + "message": "ਜਦੋਂ ਕਿਸੇ ਫਿਲਟਰ ਸੂਚੀ ਨੂੰ ਅੱਪਡੇਟ ਕਰਨ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ ਤਾਂ ਬੇਤਰਤੀਬੇ ਚੁਣਿਆ ਗਿਆ CDN ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ।", "description": "Shown in the About pane" }, "aboutBackupDataButton": { @@ -1072,7 +1072,7 @@ "description": "English: Reset to default settings..." }, "aboutRestoreDataConfirm": { - "message": "All your settings will be overwritten using data backed up on {{time}}, and uBlock₀ will restart.\n\nOverwrite all existing settings using backed up data?", + "message": "ਤੁਹਾਡੀਆਂ ਸਾਰੀਆਂ ਸੈਟਿੰਗਾਂ {{time}} 'ਤੇ ਬੈਕਅੱਪ ਕੀਤੇ ਗਏ ਡੇਟਾ ਦੀ ਵਰਤੋਂ ਕਰਕੇ ਓਵਰਰਾਈਟ ਕਰ ਦਿੱਤੀਆਂ ਜਾਣਗੀਆਂ, ਅਤੇ uBlock₀ ਮੁੜ ਚਾਲੂ ਹੋ ਜਾਵੇਗਾ।\n\nਕੀ ਬੈਕਅੱਪ ਕੀਤੇ ਡੇਟਾ ਦੀ ਵਰਤੋਂ ਕਰਕੇ ਸਾਰੀਆਂ ਮੌਜੂਦਾ ਸੈਟਿੰਗਾਂ ਨੂੰ ਓਵਰਰਾਈਟ ਕਰਨਾ ਹੈ?", "description": "Message asking user to confirm restore" }, "aboutRestoreDataError": { @@ -1176,7 +1176,7 @@ "description": "Button text to navigate to the blocked page" }, "docblockedRedirectPrompt": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "ਬਲੌਕ ਕੀਤਾ ਪੰਨਾ ਕਿਸੇ ਹੋਰ ਸਾਈਟ 'ਤੇ ਰੀਡਾਇਰੈਕਟ ਕਰਨਾ ਚਾਹੁੰਦਾ ਹੈ। ਜੇਕਰ ਤੁਸੀਂ ਅੱਗੇ ਵਧਣਾ ਚੁਣਦੇ ਹੋ, ਤਾਂ ਤੁਸੀਂ ਸਿੱਧੇ ਇਸ 'ਤੇ ਨੈਵੀਗੇਟ ਕਰੋਗੇ: {{url}}", "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { @@ -1184,7 +1184,7 @@ "description": "The label which prepend the actual reason why a page was blocked" }, "docblockedReasonMalicious": { - "message": "Malicious", + "message": "ਖਤਰਨਾਕ", "description": "An actual reason why a page was blocked" }, "docblockedReasonTracker": { @@ -1192,7 +1192,7 @@ "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { - "message": "Disreputable", + "message": "ਬਦਨਾਮ", "description": "An actual reason why a page was blocked" }, "cloudPush": { @@ -1256,7 +1256,7 @@ "description": "Placeholder string for input field used to capture a keyboard shortcut" }, "genericMergeViewScrollLock": { - "message": "Toggle locked scrolling", + "message": "ਲੌਕ ਕੀਤੇ ਸਕ੍ਰੌਲਿੰਗ ਨੂੰ ਟੌਗਲ ਕਰੋ", "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" }, "genericCopyToClipboard": { @@ -1268,7 +1268,7 @@ "description": "Label for buttons used to select all text in editor" }, "toggleCosmeticFiltering": { - "message": "Toggle cosmetic filtering", + "message": "ਕਾਸਮੈਟਿਕ ਫਿਲਟਰਿੰਗ ਨੂੰ ਟੌਗਲ ਕਰੋ", "description": "Label for keyboard shortcut used to toggle cosmetic filtering" }, "toggleJavascript": { @@ -1276,7 +1276,7 @@ "description": "Label for keyboard shortcut used to toggle no-scripting switch" }, "relaxBlockingMode": { - "message": "Relax blocking mode", + "message": "ਬਲਾਕਿੰਗ ਮੋਡ ਨੂੰ ਢਿੱਲਾ ਕਰੋ", "description": "Label for keyboard shortcut used to relax blocking mode" }, "storageUsed": { @@ -1304,7 +1304,7 @@ "description": "Summary of number of errors as reported by the linter " }, "unprocessedRequestTooltip": { - "message": "Could not filter properly at browser launch. Reload the page to ensure proper filtering.", + "message": "ਬ੍ਰਾਊਜ਼ਰ ਸ਼ੁਰੂ ਹੋਣ 'ਤੇ ਸਹੀ ਢੰਗ ਨਾਲ ਫਿਲਟਰ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ। ਸਹੀ ਫਿਲਟਰਿੰਗ ਨੂੰ ਯਕੀਨੀ ਬਣਾਉਣ ਲਈ ਪੰਨਾ ਮੁੜ ਲੋਡ ਕਰੋ।", "description": "A warning which will appear in the popup panel if needed" }, "dummy": { diff --git a/src/_locales/pl/messages.json b/src/_locales/pl/messages.json index 4802a3a0669c4..e88b2001aedee 100644 --- a/src/_locales/pl/messages.json +++ b/src/_locales/pl/messages.json @@ -960,7 +960,7 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "Aby uniknąć obciążania wolontariuszy zduplikowanymi zgłoszeniami, sprawdź, czy problem nie został już zgłoszony.", + "message": "Sprawdź, czy problem nie został już zgłoszony, aby uniknąć obciążania wolontariuszy duplikatami raportów. Uwaga: kliknięcie przycisku spowoduje wysłanie źródła strony do serwisu GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { diff --git a/src/_locales/pt_BR/messages.json b/src/_locales/pt_BR/messages.json index a8c575b011a80..f9887e5d6af07 100644 --- a/src/_locales/pt_BR/messages.json +++ b/src/_locales/pt_BR/messages.json @@ -4,7 +4,7 @@ "description": "extension name." }, "extShortDesc": { - "message": "Até que enfim, um bloqueador eficiente. Bem otimizado para CPU e memória.", + "message": "Finalmente, um bloqueador eficiente. Com baixo uso de CPU e memória.", "description": "this will be in the Chrome web store: must be 132 characters or less" }, "dashboardName": { @@ -16,7 +16,7 @@ "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "Ficar", + "message": "Ficar aqui", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { diff --git a/src/_locales/pt_PT/messages.json b/src/_locales/pt_PT/messages.json index a599052c871e9..4f4ca7817d208 100644 --- a/src/_locales/pt_PT/messages.json +++ b/src/_locales/pt_PT/messages.json @@ -12,7 +12,7 @@ "description": "English: uBlock₀ — Dashboard" }, "dashboardUnsavedWarning": { - "message": "Atenção! Tem alterações não guardadas", + "message": "Atenção: tem alterações não guardadas!", "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Regras locais: esta coluna é para as regras que se aplicam apenas a este site.\nAs regras locais sobrepõem-se às regras globais.", + "message": "Regras locais: esta coluna é para as regras que se aplicam apenas ao site atual.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -332,7 +332,7 @@ "description": "English: Make use of context menu where appropriate" }, "settingsColorBlindPrompt": { - "message": "Cores amigáveis para daltónicos", + "message": "Cores adequadas para daltónicos", "description": "English: Color-blind friendly" }, "settingsAppearance": { @@ -364,7 +364,7 @@ "description": "English: " }, "settingsWebRTCIPAddressHiddenPrompt": { - "message": "Impedir o WebRTC de vazar endereços IP locais", + "message": "Impedir fugas de endereços IP locais através do WebRTC", "description": "English: " }, "settingPerSiteSwitchGroup": { @@ -404,7 +404,7 @@ "description": "Section for controlling advanced-user settings" }, "settingsAdvancedSynopsis": { - "message": "Funcionalidades adequadas apenas para utilizadores avançados", + "message": "Funcionalidades adequadas apenas para utilizadores técnicos", "description": "Description of section controlling advanced-user settings" }, "settingsAdvancedUserSettings": { @@ -480,7 +480,7 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "Proteção contra malware, segurança", + "message": "Proteção contra malware e segurança", "description": "Filter lists section name" }, "3pGroupSocial": { @@ -836,7 +836,7 @@ "description": "Below this sentence, the filter list(s) in which the filter was found" }, "loggerStaticFilteringFinderSentence2": { - "message": "O filtro estático não pôde ser encontrado em quaisquer das listas de filtros ativadas atualmente", + "message": "Não foi possível encontrar o filtro estático em nenhuma das listas de filtros atualmente ativadas", "description": "Message to show when a filter cannot be found in any filter lists" }, "loggerSettingDiscardPrompt": { @@ -848,7 +848,7 @@ "description": "A logger setting" }, "loggerSettingPerTabMaxLoads": { - "message": "Preservar no máximo {{input}} carregamentos de página por separador", + "message": "Preservar no máximo {{input}} recargas de página por separador", "description": "A logger setting" }, "loggerSettingPerTabMaxEntries": { @@ -952,7 +952,7 @@ "description": "Header of 'Troubleshooting Information' section in Support pane" }, "supportS5P1": { - "message": "Abaixo encontra-se informação técnica que pode ser útil quando voluntários estão a tentar ajudar-lhe a resolver um problema.", + "message": "Abaixo encontra-se informação técnica que pode ser útil quando voluntários estão a tentar ajudá-lo a resolver um problema.", "description": "First paragraph of 'Troubleshooting Information' section in Support pane" }, "supportS6H": { @@ -968,7 +968,7 @@ "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S2": { - "message": "Verifique se o problema ainda existe após o recarregamento da página web problemática.", + "message": "Verifique se o problema persiste após recarregar a página web problemática.", "description": "A paragraph in the filter issue reporter section" }, "supportS6URL": { @@ -1008,7 +1008,7 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leva a badware e phishing", + "message": "Leva a badware e/ou phishing", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { @@ -1024,7 +1024,7 @@ "description": "" }, "aboutCode": { - "message": "Código fonte (GPLv3)", + "message": "Código-fonte (GPLv3)", "description": "English: Source code (GPLv3)" }, "aboutContributors": { @@ -1032,7 +1032,7 @@ "description": "English: Contributors" }, "aboutSourceCode": { - "message": "Código fonte", + "message": "Código-fonte", "description": "Link text to source code repo" }, "aboutTranslations": { @@ -1076,7 +1076,7 @@ "description": "Message asking user to confirm restore" }, "aboutRestoreDataError": { - "message": "Os dados não puderam ser lidos ou são inválidos", + "message": "Não foi possível ler os dados ou estes são inválidos", "description": "Message to display when an error occurred during restore" }, "aboutResetDataConfirm": { @@ -1144,7 +1144,7 @@ "description": "label to be used for the parameter-less URL: https://cloud.githubusercontent.com/assets/585534/9832014/bfb1b8f0-593b-11e5-8a27-fba472a5529a.png" }, "docblockedFoundIn": { - "message": "Encontrado em:", + "message": "O filtro foi encontrado em:", "description": "English: List of filter list names follows" }, "docblockedBack": { @@ -1248,7 +1248,7 @@ "description": "A context menu entry, present when large media elements have been blocked on the current site" }, "contextMenuViewSource": { - "message": "Ver código fonte…", + "message": "Ver código-fonte…", "description": "A context menu entry, to view the source code of the target resource" }, "shortcutCapturePlaceholder": { @@ -1256,7 +1256,7 @@ "description": "Placeholder string for input field used to capture a keyboard shortcut" }, "genericMergeViewScrollLock": { - "message": "Alternar deslocamento bloqueado", + "message": "Alternar bloqueio da deslocação", "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" }, "genericCopyToClipboard": { @@ -1304,7 +1304,7 @@ "description": "Summary of number of errors as reported by the linter " }, "unprocessedRequestTooltip": { - "message": "Não foi possível filtrar adequadamente no arranque do navegador. Recarregue a página para assegurar uma filtragem adequada.", + "message": "Não foi possível filtrar corretamente no arranque do navegador. Recarregue a página para assegurar uma filtragem adequada.", "description": "A warning which will appear in the popup panel if needed" }, "dummy": { diff --git a/src/_locales/ro/messages.json b/src/_locales/ro/messages.json index 3c5347a6b2660..fe9359ef8d1a4 100644 --- a/src/_locales/ro/messages.json +++ b/src/_locales/ro/messages.json @@ -40,7 +40,7 @@ "description": "appears as tab name in dashboard" }, "whitelistPageName": { - "message": "Situri de încredere", + "message": "Siteuri de încredere", "description": "appears as tab name in dashboard" }, "shortcutsPageName": { @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Reguli locale: această coloană este pentru regulile care se aplică doar site-ului curent.\nRegulile locale suprascriu pe cele globale.", + "message": "Reguli locale: această coloană este pentru regulile care se aplică doar site-ului curent.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -596,7 +596,7 @@ "description": "" }, "rulesExport": { - "message": "Exportă în fișier...", + "message": "Exportă în fișier…", "description": "Button in the 'My rules' pane" }, "rulesDefaultFileName": { @@ -632,11 +632,11 @@ "description": "A concise description of the 'Trusted sites' pane." }, "whitelistImport": { - "message": "Importă și adaugă", + "message": "Importă și adaugă…", "description": "Button in the 'Trusted sites' pane" }, "whitelistExport": { - "message": "Exportă", + "message": "Exportă…", "description": "Button in the 'Trusted sites' pane" }, "whitelistExportFilename": { @@ -900,11 +900,11 @@ "description": "Text for button which open an external web page in Support pane" }, "supportReportSpecificButton": { - "message": "Crează o nouă sesizare", + "message": "Creează o nouă sesizare pe GitHub", "description": "Text for button which open an external web page in Support pane" }, "supportFindSpecificButton": { - "message": "Găsește sesizări similare", + "message": "Găsește sesizări similare pe GitHub", "description": "A clickable link in the filter issue reporter section" }, "supportS1H": { @@ -960,7 +960,7 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "Pentru a evita suprasolicitarea voluntarilor, vă rugăm să verificați dacă această problemă nu a fost deja raportată.", + "message": "Pentru a evita suprasolicitarea voluntarilor, vă rugăm să verificați dacă această problemă nu a fost deja raportată. Notă: dacă faceți clic pe buton, originea paginii va fi trimisă către GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { @@ -1248,7 +1248,7 @@ "description": "A context menu entry, present when large media elements have been blocked on the current site" }, "contextMenuViewSource": { - "message": "Vezi sursa", + "message": "Vezi sursa…", "description": "A context menu entry, to view the source code of the target resource" }, "shortcutCapturePlaceholder": { @@ -1304,7 +1304,7 @@ "description": "Summary of number of errors as reported by the linter " }, "unprocessedRequestTooltip": { - "message": "Nu s-a putut filtra corespunzător in timpul lansării browser-ului. Reîncarcați paginile", + "message": "Nu s-a putut filtra corespunzător in timpul lansării browser-ului. Reîncărcați pagina pentru a asigura o filtrare corectă.", "description": "A warning which will appear in the popup panel if needed" }, "dummy": { diff --git a/src/_locales/si/messages.json b/src/_locales/si/messages.json index fc4255dd27cb6..20732cbc2cb8a 100644 --- a/src/_locales/si/messages.json +++ b/src/_locales/si/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "දේශීය නීති: මෙම තීරුව වත්මන් අඩවියට පමණක් අදාළ වන නීති සඳහා වේ.\nදේශීය නීති ගෝලීය නීති අභිබවා යයි.", + "message": "දේශීය නීති: මෙම තීරුව වත්මන් අඩවියට පමණක් අදාළ වන නීති සඳහා වේ.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -1180,19 +1180,19 @@ "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { - "message": "Reason:", + "message": "හේතුව:", "description": "The label which prepend the actual reason why a page was blocked" }, "docblockedReasonMalicious": { - "message": "Malicious", + "message": "හානිකර", "description": "An actual reason why a page was blocked" }, "docblockedReasonTracker": { - "message": "Tracker", + "message": "ලුහුබඳින්නා", "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { - "message": "Disreputable", + "message": "අපකීර්තිමත්", "description": "An actual reason why a page was blocked" }, "cloudPush": { diff --git a/src/_locales/sk/messages.json b/src/_locales/sk/messages.json index fd590d2460a2b..52f97c7b71b24 100644 --- a/src/_locales/sk/messages.json +++ b/src/_locales/sk/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Lokálne pravidlá: tento stĺpec slúži pre pravidlá, ktoré platia len pre aktuálny web.\nLokálne pravidlá prepisujú globálne pravidlá.", + "message": "Lokálne pravidlá: tento stĺpec slúži pre pravidlá, ktoré platia len pre aktuálny web.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -480,7 +480,7 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "Domény malvéru", + "message": "Ochrana pred škodlivým softvérom, bezpečnosť", "description": "Filter lists section name" }, "3pGroupSocial": { @@ -960,7 +960,7 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "Aby ste dobrovoľníkov nezaťažovali duplicitnými hláseniami, overte si, či už problém nebol nahlásený.", + "message": "Aby ste dobrovoľníkov nezaťažovali duplicitnými hláseniami, overte si, či už problém nebol nahlásený. Poznámka: kliknutím na tlačidlo sa odošle pôvodná stránka na GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { diff --git a/src/_locales/sl/messages.json b/src/_locales/sl/messages.json index eb21a35223156..4cb1ddf97e564 100644 --- a/src/_locales/sl/messages.json +++ b/src/_locales/sl/messages.json @@ -12,11 +12,11 @@ "description": "English: uBlock₀ — Dashboard" }, "dashboardUnsavedWarning": { - "message": "Pozor! Spremembe niso shranjene", + "message": "Pozor: spremembe niso shranjene!", "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "Ostani", + "message": "Ostani tu", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { @@ -276,11 +276,11 @@ "description": "Example of use: Version 1.26.4" }, "popup3pScriptFilter": { - "message": "script", + "message": "skripta", "description": "Appears as an option to filter out firewall rows" }, "popup3pFrameFilter": { - "message": "frame", + "message": "okvir", "description": "Appears as an option to filter out firewall rows" }, "pickerCreate": { @@ -360,7 +360,7 @@ "description": "English: " }, "settingsHyperlinkAuditingDisabledPrompt": { - "message": "Onemogoči revizijo hiperlinkov (Hyperlink-auditing)", + "message": "Onemogoči sledenje hiperpovezavam", "description": "English: " }, "settingsWebRTCIPAddressHiddenPrompt": { @@ -380,7 +380,7 @@ "description": "" }, "settingsNoLargeMediaPrompt": { - "message": "Blokiraj medijske elemente večje kot {input:number} kB", + "message": "Blokiraj medijske elemente večje kot {{input}} KB", "description": "" }, "settingsNoRemoteFontsPrompt": { @@ -396,7 +396,7 @@ "description": "background information: https://github.com/gorhill/uBlock/issues/3150" }, "settingsUncloakCnamePrompt": { - "message": "Uncloak canonical names", + "message": "Razkrij kanonična imena", "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" }, "settingsAdvanced": { @@ -440,7 +440,7 @@ "description": "A button in the in the _3rd-party filters_ pane" }, "3pParseAllABPHideFiltersPrompt1": { - "message": "Razčleni in uveljavi kozmetične filtre.", + "message": "Razčleni in uveljavi kozmetične filtre", "description": "English: Parse and enforce Adblock+ element hiding filters." }, "3pParseAllABPHideFiltersInfo": { @@ -480,15 +480,15 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "Zlonamerne domene", + "message": "Zaščita pred zlonamerno programsko opremo, varnost", "description": "Filter lists section name" }, "3pGroupSocial": { - "message": "Social widgets", + "message": "Družbeni gradniki", "description": "Filter lists section name" }, "3pGroupCookies": { - "message": "Cookie notices", + "message": "Obvestila o piškotkih", "description": "Filter lists section name" }, "3pGroupAnnoyances": { @@ -508,11 +508,11 @@ "description": "Filter lists section name" }, "3pImport": { - "message": "Uvozi ...", + "message": "Uvozi…", "description": "The label for the checkbox used to import external filter lists" }, "3pExternalListsHint": { - "message": "En URL na vrstico. Vrstice s predpono ‘!’ in neveljavni URL-ji bodo prezrti.", + "message": "En URL na vrstico. Neveljavni URL-ji bodo tiho prezrti.", "description": "Short information about how to use the textarea to import external filter lists by URL" }, "3pExternalListObsolete": { @@ -524,11 +524,11 @@ "description": "used as a tooltip for eye icon beside a list" }, "3pLastUpdate": { - "message": "Zadnja posodobitev: {{ago}}", + "message": "Zadnja posodobitev: {{ago}}. Kliknite za prisilno posodobitev.", "description": "used as a tooltip for the clock icon beside a list" }, "3pUpdating": { - "message": "Posodabljanje ...", + "message": "Posodabljanje…", "description": "used as a tooltip for the spinner icon beside a list" }, "3pNetworkError": { @@ -536,23 +536,23 @@ "description": "used as a tooltip for error icon beside a list" }, "1pTrustWarning": { - "message": "Do not add filters from untrusted sources.", + "message": "Ne dodajajte filtrov iz nezaupanja vrednih virov.", "description": "Warning against copy-pasting filters from random sources" }, "1pEnableMyFiltersLabel": { - "message": "Enable my custom filters", + "message": "Omogoči moje filtre po meri", "description": "Label for the checkbox use to enable/disable 'My filters' list" }, "1pTrustMyFiltersLabel": { - "message": "Allow custom filters requiring trust", + "message": "Dovoli filtre po meri, ki zahtevajo zaupanje", "description": "Label for the checkbox use to trust the content of 'My filters' list" }, "1pImport": { - "message": "Uvozi in dodaj", + "message": "Uvozi in dodaj …", "description": "Button in the 'My filters' pane" }, "1pExport": { - "message": "Izvozi", + "message": "Izvozi…", "description": "Button in the 'My filters' pane" }, "1pExportFilename": { @@ -592,11 +592,11 @@ "description": "Will discard manually-edited content and exit manual-edit mode" }, "rulesImport": { - "message": "Uvozi iz datoteke...", + "message": "Uvozi iz datoteke…", "description": "" }, "rulesExport": { - "message": "Izvozi v datoteko", + "message": "Izvozi v datoteko…", "description": "Button in the 'My rules' pane" }, "rulesDefaultFileName": { @@ -612,7 +612,7 @@ "description": "English: dynamic rule syntax and full documentation." }, "rulesSort": { - "message": "Razvrsti", + "message": "Razvrsti:", "description": "English: label for sort option." }, "rulesSortByType": { @@ -628,7 +628,7 @@ "description": "English: a sort option for list of rules." }, "whitelistPrompt": { - "message": "Vaš seznam gostiteljskih naslovov, za katere želite, da je uBlock₀ izklopljen. En vnos na vrstico. Neveljavna gostiteljska imena bodo brez opozoril ignorirana.", + "message": "Vaš seznam gostiteljskih naslovov, za katere želite, da je uBlock Origin izklopljen. En vnos na vrstico.", "description": "A concise description of the 'Trusted sites' pane." }, "whitelistImport": { @@ -928,7 +928,7 @@ "description": "Header of 'Filter issues' section in Support pane" }, "supportS3P1": { - "message": "Prijavi težave s filtrom na posameznih straneh v uBlockOrigin/uAssets sledilnik težav.", + "message": "Prijavi težave s filtrom na posameznih straneh v uBlockOrigin/uAssets sledilnik težav. Zahteva GitHub račun.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS3P2": { @@ -952,7 +952,7 @@ "description": "Header of 'Troubleshooting Information' section in Support pane" }, "supportS5P1": { - "message": "Below is technical information that might be useful when volunteers are trying to help you solve a problem.", + "message": "Spodaj so tehnične informacije, ki so lahko v pomoč prostovoljcem, ko vam skušajo rešiti težavo.", "description": "First paragraph of 'Troubleshooting Information' section in Support pane" }, "supportS6H": { @@ -964,11 +964,11 @@ "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { - "message": "Filter lists are updated daily. Be sure your issue has not already been addressed in the most recent filter lists.", + "message": "Seznami filtrov se posodabljajo dnevno. Prepričajte se, da vaša težava še ni bila rešena v najnovejših seznamih filtrov.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S2": { - "message": "Verify that the issue still exists after reloading the problematic web page.", + "message": "Preverite, ali težava še vedno obstaja po ponovnem nalaganju problematične spletne strani.", "description": "A paragraph in the filter issue reporter section" }, "supportS6URL": { @@ -976,7 +976,7 @@ "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "Spletna stran …", + "message": "Spletna stran…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { @@ -988,11 +988,11 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "Ima prekrivne elemente ali druge nadloge", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBlock Origin", + "message": "Zazna uBlock Origin", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { @@ -1000,19 +1000,19 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBlock Origin is enabled", + "message": "Ne deluje pravilno, ko je uBlock Origin omogočen", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "Odpre neželene zavihke ali okna", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "Vodi do zlonamerne programske opreme, lažnega predstavljanja", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "Označi spletno stran kot “NSFW” (“Ni primerno za delo”)", "description": "A checkbox to use for NSFW sites" }, "aboutPrivacyPolicy": { @@ -1048,11 +1048,11 @@ "description": "Shown in the About pane" }, "aboutCDNs": { - "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "message": "uBO-jevi lastni seznami filtrov so brezplačno gostovani na naslednjih CDN-ih:", "description": "Shown in the About pane" }, "aboutCDNsInfo": { - "message": "Ob posodobitvi seznama filtrov se uporabi naključno izbran CDN", + "message": "Ob posodobitvi seznama filtrov se uporabi naključno izbran CDN.", "description": "Shown in the About pane" }, "aboutBackupDataButton": { @@ -1128,7 +1128,7 @@ "description": "Firefox-specific: appears as 'uBlock₀ (off)'" }, "docblockedTitle": { - "message": "Page blocked", + "message": "Stran blokirana", "description": "Used as a title for the document-blocked page" }, "docblockedPrompt1": { @@ -1136,7 +1136,7 @@ "description": "Used in the strict-blocking page" }, "docblockedPrompt2": { - "message": "Zaradi sledečega filtra", + "message": "To se je zgodilo zaradi sledečega filtra:", "description": "Used in the strict-blocking page" }, "docblockedNoParamsPrompt": { @@ -1156,7 +1156,7 @@ "description": "English: Close this window" }, "docblockedDontWarn": { - "message": "Don't warn me again about this site", + "message": "Ne opozarjaj me več za to spletno mesto", "description": "Label for checkbox in document-blocked page" }, "docblockedProceed": { @@ -1172,27 +1172,27 @@ "description": "English: Permanently" }, "docblockedDisable": { - "message": "Proceed", + "message": "Nadaljuj", "description": "Button text to navigate to the blocked page" }, "docblockedRedirectPrompt": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "Blokirana stran želi preusmeriti na drugo spletno mesto. Če izberete nadaljevanje, boste neposredno preusmerjeni na: {{url}}", "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { - "message": "Reason:", + "message": "Razlog:", "description": "The label which prepend the actual reason why a page was blocked" }, "docblockedReasonMalicious": { - "message": "Malicious", + "message": "Zlonamerno", "description": "An actual reason why a page was blocked" }, "docblockedReasonTracker": { - "message": "Tracker", + "message": "Sledilnik", "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { - "message": "Disreputable", + "message": "Slab sloves", "description": "An actual reason why a page was blocked" }, "cloudPush": { @@ -1236,11 +1236,11 @@ "description": "" }, "contextMenuBlockElementInFrame": { - "message": "Blokiraj element v okvirju", + "message": "Blokiraj element v okvirju …", "description": "An entry in the browser's contextual menu" }, "contextMenuSubscribeToList": { - "message": "Naroči se na seznam filtrov..", + "message": "Naroči se na seznam filtrov…", "description": "An entry in the browser's contextual menu" }, "contextMenuTemporarilyAllowLargeMediaElements": { @@ -1248,7 +1248,7 @@ "description": "A context menu entry, present when large media elements have been blocked on the current site" }, "contextMenuViewSource": { - "message": "View source code…", + "message": "Prikaži izvorno kodo…", "description": "A context menu entry, to view the source code of the target resource" }, "shortcutCapturePlaceholder": { @@ -1272,11 +1272,11 @@ "description": "Label for keyboard shortcut used to toggle cosmetic filtering" }, "toggleJavascript": { - "message": "Toggle JavaScript", + "message": "Preklopi JavaScript", "description": "Label for keyboard shortcut used to toggle no-scripting switch" }, "relaxBlockingMode": { - "message": "Sprostite način blokiranja.", + "message": "Sprostite način blokiranja", "description": "Label for keyboard shortcut used to relax blocking mode" }, "storageUsed": { @@ -1300,11 +1300,11 @@ "description": "Message used in frame placeholders" }, "linterMainReport": { - "message": "Errors: {{count}}", + "message": "Napake: {{count}}", "description": "Summary of number of errors as reported by the linter " }, "unprocessedRequestTooltip": { - "message": "Could not filter properly at browser launch. Reload the page to ensure proper filtering.", + "message": "Ob zagonu brskalnika filtriranje ni potekalo pravilno. Ponovno naložite stran, da zagotovite pravilno filtriranje.", "description": "A warning which will appear in the popup panel if needed" }, "dummy": { diff --git a/src/_locales/so/messages.json b/src/_locales/so/messages.json index 7ec1742bd9fcf..f36a82ee927ae 100644 --- a/src/_locales/so/messages.json +++ b/src/_locales/so/messages.json @@ -16,7 +16,7 @@ "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "Joog", + "message": "Halkan joog", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { @@ -72,7 +72,7 @@ "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." }, "popupPowerSwitchInfo1": { - "message": "Click to disable uBlock₀ for this site.\n\nCtrl+click to disable uBlock₀ only on this page.", + "message": "Riix si aad u demiso uBlock₀ ee boggan.\n\nCtrl+riix si aad u demiso uBlock₀ kaliya boggan.", "description": "Message to be read by screen readers" }, "popupPowerSwitchInfo2": { @@ -84,7 +84,7 @@ "description": "English: requests blocked" }, "popupBlockedOnThisPagePrompt": { - "message": "on this page", + "message": "boggan", "description": "English: on this page" }, "popupBlockedStats": { @@ -128,7 +128,7 @@ "description": "Tooltip used for the logger icon in the panel" }, "popupTipReport": { - "message": "Report an issue on this website", + "message": "Shey dhibaato ka jirta websaydhkan", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipNoPopups": { @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "JavaScript", + "message": "Xeerarka deegaanka: tiirarkani waxaa loogu talagalay xeerarka khuseeya kaliya bogga hadda jira.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -276,11 +276,11 @@ "description": "Example of use: Version 1.26.4" }, "popup3pScriptFilter": { - "message": "script", + "message": "qoraal", "description": "Appears as an option to filter out firewall rows" }, "popup3pFrameFilter": { - "message": "frame", + "message": "qaab", "description": "Appears as an option to filter out firewall rows" }, "pickerCreate": { @@ -336,15 +336,15 @@ "description": "English: Color-blind friendly" }, "settingsAppearance": { - "message": "Appearance", + "message": "Muqaal", "description": "Section for controlling user interface appearance" }, "settingsThemeLabel": { - "message": "Theme", + "message": "Mawduuc", "description": "Label for checkbox to enable a custom dark theme" }, "settingsThemeAccent0Label": { - "message": "Custom accent color", + "message": "Midab accan custom ah", "description": "Label for checkbox to pick an accent color" }, "settingsCloudStorageEnabledPrompt": { @@ -400,11 +400,11 @@ "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" }, "settingsAdvanced": { - "message": "Advanced", + "message": "Horumarsan", "description": "Section for controlling advanced-user settings" }, "settingsAdvancedSynopsis": { - "message": "Features suitable only for technical users", + "message": "Astaamooyin ku habboon oo keliya isticmaaleyaasha farsamada yaqaaniin", "description": "Description of section controlling advanced-user settings" }, "settingsAdvancedUserSettings": { @@ -456,7 +456,7 @@ "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." }, "3pSuspendUntilListsAreLoaded": { - "message": "Suspend network activity until all filter lists are loaded", + "message": "Jooji dhaqdhaqaaqa shabakada ilaa inta aan la soo rarin dhammaan liisaska shaandhada", "description": "A checkbox in the 'Filter lists' pane" }, "3pListsOfBlockedHostsHeader": { @@ -480,15 +480,15 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "Malware protection, security", + "message": "Ilaalinta Malware-ka, amniga", "description": "Filter lists section name" }, "3pGroupSocial": { - "message": "Social widgets", + "message": "Qalabyada bulshada", "description": "Filter lists section name" }, "3pGroupCookies": { - "message": "Cookie notices", + "message": "Ogeysiisyada cookies", "description": "Filter lists section name" }, "3pGroupAnnoyances": { @@ -536,15 +536,15 @@ "description": "used as a tooltip for error icon beside a list" }, "1pTrustWarning": { - "message": "Do not add filters from untrusted sources.", + "message": "Ha ku darin shaandhooyin ilo aan la kalsooni karin.", "description": "Warning against copy-pasting filters from random sources" }, "1pEnableMyFiltersLabel": { - "message": "Enable my custom filters", + "message": "Daawo shaandhooyinka aan ku habeeyay", "description": "Label for the checkbox use to enable/disable 'My filters' list" }, "1pTrustMyFiltersLabel": { - "message": "Allow custom filters requiring trust", + "message": "Oggolow shaandhooyin habaysan oo u baahan kalsooni", "description": "Label for the checkbox use to trust the content of 'My filters' list" }, "1pImport": { @@ -900,11 +900,11 @@ "description": "Text for button which open an external web page in Support pane" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "Samee warbixin cusub oo ku taal GitHub", "description": "Text for button which open an external web page in Support pane" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "Raadi warbixino la mid ah oo ku yaal GitHub", "description": "A clickable link in the filter issue reporter section" }, "supportS1H": { @@ -956,63 +956,63 @@ "description": "First paragraph of 'Troubleshooting Information' section in Support pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "Soo sheeg dhibaatada shaandhada", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "Si looga fogaado in loola culeeyo mutadawiciinta warbixino isku mid ah, fadlan hubi in dhibaatada aan weli la soo sheegin. Fiiro gaar ah: gujinta batoomada waxay keenaysaa in asalka bogga loo diro GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { - "message": "Filter lists are updated daily. Be sure your issue has not already been addressed in the most recent filter lists.", + "message": "Liisaska shaandhooyinka waa la cusbooneysiiyaa maalin kasta. Hubi in dhibaatadaada aan weli laga hadlin liisaska shaandhada ee ugu dambeeyay.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S2": { - "message": "Verify that the issue still exists after reloading the problematic web page.", + "message": "Xaqiiji in dhibaatadu wali jirto ka dib markaad dib u soo dejiso bogga websaydhka ee dhibaatada leh.", "description": "A paragraph in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "Ciwaanka bogga websaydhka:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "Bogga websaydhka…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- Dooro gelin --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "Wuxuu muujiyaa xayeysiisyo ama hadhaagii xayeysiiska", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "Wuxuu leeyahay dahaar ama waxyaabo kale oo dhib badan", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBlock Origin", + "message": "Wuxuu ogaadaa uBlock Origin", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "Wuxuu leeyahay dhibaatooyin la xiriira gaar ahaaneed", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBlock Origin is enabled", + "message": "Waxay cilladeeyaan marka uBlock Origin la daayo", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "Wuxuu furayaa tabo ama daaqado aan la rabin", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "Wuxuu u horseedaa barnaamij xun, khiyaamo (phishing)", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "U calaamadee bogga websaydhka sida “NSFW” (“Aan Ammaan u ahayn Shaqada”)", "description": "A checkbox to use for NSFW sites" }, "aboutPrivacyPolicy": { @@ -1104,7 +1104,7 @@ "description": "English: an hour ago" }, "elapsedManyHoursAgo": { - "message": "{{value}} hours ago", + "message": "{{value}} saacadood ka hor", "description": "English: {{value}} hours ago" }, "elapsedOneDayAgo": { @@ -1120,7 +1120,7 @@ "description": "Firefox/Fennec-specific: Show Dashboard" }, "showNetworkLogButton": { - "message": "Show Logger", + "message": "Muuji Diiwaangeliye", "description": "Firefox/Fennec-specific: Show Logger" }, "fennecMenuItemBlockingOff": { @@ -1128,7 +1128,7 @@ "description": "Firefox-specific: appears as 'uBlock₀ (off)'" }, "docblockedTitle": { - "message": "Page blocked", + "message": "Bog la xannibay", "description": "Used as a title for the document-blocked page" }, "docblockedPrompt1": { @@ -1140,7 +1140,7 @@ "description": "Used in the strict-blocking page" }, "docblockedNoParamsPrompt": { - "message": "without parameters", + "message": "iyadoo aan lahayn cabbirro", "description": "label to be used for the parameter-less URL: https://cloud.githubusercontent.com/assets/585534/9832014/bfb1b8f0-593b-11e5-8a27-fba472a5529a.png" }, "docblockedFoundIn": { @@ -1156,7 +1156,7 @@ "description": "English: Close this window" }, "docblockedDontWarn": { - "message": "Don't warn me again about this site", + "message": "Ha igu digin mar labaad oo ku saabsan boggan", "description": "Label for checkbox in document-blocked page" }, "docblockedProceed": { @@ -1172,27 +1172,27 @@ "description": "English: Permanently" }, "docblockedDisable": { - "message": "Proceed", + "message": "Sii wad", "description": "Button text to navigate to the blocked page" }, "docblockedRedirectPrompt": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "Bogga la xannibay wuxuu rabaa inuu u wareego bog kale. Haddii aad doorato inaad sii waddo, waxaad si toos ah ugu dhaadhacdaa: {{url}}", "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { - "message": "Reason:", + "message": "Sababta:", "description": "The label which prepend the actual reason why a page was blocked" }, "docblockedReasonMalicious": { - "message": "Malicious", + "message": "Khatar ah", "description": "An actual reason why a page was blocked" }, "docblockedReasonTracker": { - "message": "Tracker", + "message": "Raad-raace", "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { - "message": "Disreputable", + "message": "Sumcad xumo leh", "description": "An actual reason why a page was blocked" }, "cloudPush": { @@ -1248,7 +1248,7 @@ "description": "A context menu entry, present when large media elements have been blocked on the current site" }, "contextMenuViewSource": { - "message": "View source code…", + "message": "Daawo koodka isha…", "description": "A context menu entry, to view the source code of the target resource" }, "shortcutCapturePlaceholder": { @@ -1268,11 +1268,11 @@ "description": "Label for buttons used to select all text in editor" }, "toggleCosmeticFiltering": { - "message": "Toggle cosmetic filtering", + "message": "Beddel shaandhaynta qurxinta", "description": "Label for keyboard shortcut used to toggle cosmetic filtering" }, "toggleJavascript": { - "message": "Toggle JavaScript", + "message": "Beddel JavaScript", "description": "Label for keyboard shortcut used to toggle no-scripting switch" }, "relaxBlockingMode": { @@ -1300,11 +1300,11 @@ "description": "Message used in frame placeholders" }, "linterMainReport": { - "message": "Errors: {{count}}", + "message": "Khaladaad: {{count}}", "description": "Summary of number of errors as reported by the linter " }, "unprocessedRequestTooltip": { - "message": "Could not filter properly at browser launch. Reload the page to ensure proper filtering.", + "message": "Lama shaandhayn karin si habboon markii biraawsarka la furay. Dib u soo deji bogga si aad u hubiso shaandhayn habboon.", "description": "A warning which will appear in the popup panel if needed" }, "dummy": { diff --git a/src/_locales/sq/messages.json b/src/_locales/sq/messages.json index 800eb16b18da9..1514304f5a604 100644 --- a/src/_locales/sq/messages.json +++ b/src/_locales/sq/messages.json @@ -60,7 +60,7 @@ "description": "appears as tab name in dashboard" }, "assetViewerPageName": { - "message": "uBlock₀ — Ilustruesi i aseteve", + "message": "uBlock₀ — Treguesi i aseteve", "description": "Title for the asset viewer page" }, "advancedSettingsPageName": { diff --git a/src/_locales/sr/messages.json b/src/_locales/sr/messages.json index 02dd6d947bc2e..d5dbd0a7accfa 100644 --- a/src/_locales/sr/messages.json +++ b/src/_locales/sr/messages.json @@ -16,7 +16,7 @@ "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "Остани", + "message": "Остани овде", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Локална правила: ова колона је за правила која се примењују само на тренутном сајту.\nЛокална правила имају предност у односу на општа.", + "message": "Локална правила: ова колона је за правила која се примењују само на тренутни сајт.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -324,7 +324,7 @@ "description": "English: Show the number of blocked requests on the icon" }, "settingsTooltipsPrompt": { - "message": "Онемогући описе алатке", + "message": "Онемогућите описе алата", "description": "A checkbox in the Settings pane" }, "settingsContextMenuPrompt": { @@ -900,11 +900,11 @@ "description": "Text for button which open an external web page in Support pane" }, "supportReportSpecificButton": { - "message": "Креирај нови извештај на ГитХабу", + "message": "Креирај нови извештај на GitHub-у", "description": "Text for button which open an external web page in Support pane" }, "supportFindSpecificButton": { - "message": "Пронађи сличне извештаје на ГитХабу", + "message": "Пронађи сличне извештаје на GitHub-у", "description": "A clickable link in the filter issue reporter section" }, "supportS1H": { @@ -960,7 +960,7 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "Да не бисте оптерећивали волонтере дуплим извештајима, проверите да ли је проблем већ пријављен.", + "message": "Да бисте избегли оптерећење волонтера дуплим извештајима, проверите да ли је проблем већ пријављен. Напомена: кликом на дугме, порекло странице ће бити послато GitHub-у.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { @@ -1012,7 +1012,7 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Изначите веб страницу као „NSFW“ (“Није безбедна за рад”)", + "message": "Означите веб страницу као „NSFW” („Није безбедна за рад”)", "description": "A checkbox to use for NSFW sites" }, "aboutPrivacyPolicy": { @@ -1192,7 +1192,7 @@ "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { - "message": "Неугледан", + "message": "Неугледно", "description": "An actual reason why a page was blocked" }, "cloudPush": { diff --git a/src/_locales/sv/messages.json b/src/_locales/sv/messages.json index 48802a933b91d..6112c72b15979 100644 --- a/src/_locales/sv/messages.json +++ b/src/_locales/sv/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Lokala regler: denna kolumn avser endast regler som gäller för den aktuella webbplatsen.\nLokala regler åsidosätter globala regler.", + "message": "Lokala regler: den här kolumnen avser endast regler som gäller för den aktuella webbplatsen.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { diff --git a/src/_locales/sw/messages.json b/src/_locales/sw/messages.json index 97e8e784aafb8..1b02fe4c75e6a 100644 --- a/src/_locales/sw/messages.json +++ b/src/_locales/sw/messages.json @@ -16,7 +16,7 @@ "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "Baki", + "message": "Kaa hapa", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Kanuni za ndani: safuwima hii ni ya kanuni zinazotekelezeka kwenye tovuti ya sasa pekee.\nKanuni za ndani hubatilisha kanuni za kila mahali.", + "message": "Kanuni za ndani: safuwima hii ni ya kanuni zinazotekelezeka kwenye tovuti ya sasa pekee.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -276,11 +276,11 @@ "description": "Example of use: Version 1.26.4" }, "popup3pScriptFilter": { - "message": "script", + "message": "hati", "description": "Appears as an option to filter out firewall rows" }, "popup3pFrameFilter": { - "message": "frame", + "message": "fremu", "description": "Appears as an option to filter out firewall rows" }, "pickerCreate": { @@ -480,15 +480,15 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "Vikoa vya programu hasidi", + "message": "Ulinzi wa programu hasidi, usalama", "description": "Filter lists section name" }, "3pGroupSocial": { - "message": "Social widgets", + "message": "Wijeti za kijamii", "description": "Filter lists section name" }, "3pGroupCookies": { - "message": "Cookie notices", + "message": "Arifa za kuki", "description": "Filter lists section name" }, "3pGroupAnnoyances": { @@ -536,19 +536,19 @@ "description": "used as a tooltip for error icon beside a list" }, "1pTrustWarning": { - "message": "Do not add filters from untrusted sources.", + "message": "Usiongeze vichujio kutoka kwa vyanzo visivyoaminika.", "description": "Warning against copy-pasting filters from random sources" }, "1pEnableMyFiltersLabel": { - "message": "Enable my custom filters", + "message": "Washa vichujio vyangu maalum", "description": "Label for the checkbox use to enable/disable 'My filters' list" }, "1pTrustMyFiltersLabel": { - "message": "Allow custom filters requiring trust", + "message": "Ruhusu vichujio maalum vinavyohitaji uaminifu", "description": "Label for the checkbox use to trust the content of 'My filters' list" }, "1pImport": { - "message": "Leta na ambatisha", + "message": "Leta na ambatisha…", "description": "Button in the 'My filters' pane" }, "1pExport": { @@ -596,7 +596,7 @@ "description": "" }, "rulesExport": { - "message": "Hamisha kuenda faili", + "message": "Hamisha kuenda faili…", "description": "Button in the 'My rules' pane" }, "rulesDefaultFileName": { @@ -632,7 +632,7 @@ "description": "A concise description of the 'Trusted sites' pane." }, "whitelistImport": { - "message": "Leta na ambatisha", + "message": "Leta na ambatisha…", "description": "Button in the 'Trusted sites' pane" }, "whitelistExport": { @@ -964,11 +964,11 @@ "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { - "message": "Filter lists are updated daily. Be sure your issue has not already been addressed in the most recent filter lists.", + "message": "Orodha za vichujio husasishwa kila siku. Hakikisha suala lako bado halijashughulikiwa katika orodha za hivi majuzi za vichujio.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S2": { - "message": "Verify that the issue still exists after reloading the problematic web page.", + "message": "Thibitisha kuwa suala bado lipo baada ya kupakia upya ukurasa wa wavuti wenye matatizo.", "description": "A paragraph in the filter issue reporter section" }, "supportS6URL": { @@ -1008,7 +1008,7 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "Husababisha badware, hadaa", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { @@ -1056,7 +1056,7 @@ "description": "Shown in the About pane" }, "aboutBackupDataButton": { - "message": "Cheleza kwenye faili", + "message": "Cheleza kwenye faili…", "description": "Text for button to create a backup of all settings" }, "aboutBackupFilename": { @@ -1128,7 +1128,7 @@ "description": "Firefox-specific: appears as 'uBlock₀ (off)'" }, "docblockedTitle": { - "message": "Page blocked", + "message": "Ukurasa umezuiwa", "description": "Used as a title for the document-blocked page" }, "docblockedPrompt1": { @@ -1156,7 +1156,7 @@ "description": "English: Close this window" }, "docblockedDontWarn": { - "message": "Don't warn me again about this site", + "message": "Usinionye tena kuhusu tovuti hii", "description": "Label for checkbox in document-blocked page" }, "docblockedProceed": { @@ -1172,27 +1172,27 @@ "description": "English: Permanently" }, "docblockedDisable": { - "message": "Proceed", + "message": "Endelea", "description": "Button text to navigate to the blocked page" }, "docblockedRedirectPrompt": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "Ukurasa uliozuiwa unataka kuelekeza kwenye tovuti nyingine. Ukichagua kuendelea, utaelekeza moja kwa moja hadi: {{url}}", "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { - "message": "Reason:", + "message": "Sababu:", "description": "The label which prepend the actual reason why a page was blocked" }, "docblockedReasonMalicious": { - "message": "Malicious", + "message": "Hatari", "description": "An actual reason why a page was blocked" }, "docblockedReasonTracker": { - "message": "Tracker", + "message": "Mfuatiliaji", "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { - "message": "Disreputable", + "message": "Asiyeheshimika", "description": "An actual reason why a page was blocked" }, "cloudPush": { @@ -1248,7 +1248,7 @@ "description": "A context menu entry, present when large media elements have been blocked on the current site" }, "contextMenuViewSource": { - "message": "View source code…", + "message": "Tazama msimbo wa chanzo…", "description": "A context menu entry, to view the source code of the target resource" }, "shortcutCapturePlaceholder": { @@ -1268,11 +1268,11 @@ "description": "Label for buttons used to select all text in editor" }, "toggleCosmeticFiltering": { - "message": "Toggle cosmetic filtering", + "message": "Geuza uchujaji wa vipodozi", "description": "Label for keyboard shortcut used to toggle cosmetic filtering" }, "toggleJavascript": { - "message": "Toggle JavaScript", + "message": "Geuza JavaScript", "description": "Label for keyboard shortcut used to toggle no-scripting switch" }, "relaxBlockingMode": { @@ -1300,11 +1300,11 @@ "description": "Message used in frame placeholders" }, "linterMainReport": { - "message": "Errors: {{count}}", + "message": "Makosa: {{count}}", "description": "Summary of number of errors as reported by the linter " }, "unprocessedRequestTooltip": { - "message": "Could not filter properly at browser launch. Reload the page to ensure proper filtering.", + "message": "Haikuweza kuchuja vizuri wakati wa kuzindua kivinjari.\nAnzisha upya ukurasa huu ili kuhakikisha uchujaji unaofaa.", "description": "A warning which will appear in the popup panel if needed" }, "dummy": { diff --git a/src/_locales/ta/messages.json b/src/_locales/ta/messages.json index 277764a25bf48..d7bd72df35b3e 100644 --- a/src/_locales/ta/messages.json +++ b/src/_locales/ta/messages.json @@ -16,7 +16,7 @@ "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "இருங்கள்", + "message": "இங்கேயே இரு", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "அக விதிகள்: இந்நெடுவரிசை தற்போதைய தளத்திற்கு மட்டுமே பொருந்தும் விதிகளுக்கானது.அக விதிகள் உலகளாவிய விதிகளை மீறுகின்றன.", + "message": "அக விதிகள்: இந்நெடுவரிசை தற்போதைய தளத்திற்கு மட்டுமே பொருந்தும் விதிகளுக்கானது.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -544,7 +544,7 @@ "description": "Label for the checkbox use to enable/disable 'My filters' list" }, "1pTrustMyFiltersLabel": { - "message": "Allow custom filters requiring trust", + "message": "நம்பிக்கை தேவைப்படும் தனிப்பயன் வடிப்பான்களை அனுமதிக்கவும்", "description": "Label for the checkbox use to trust the content of 'My filters' list" }, "1pImport": { @@ -920,23 +920,23 @@ "description": "Header of 'Questions and support' section in Support pane" }, "supportS2P1": { - "message": "Answers to questions and other kinds of help support is provided on the subreddit /r/uBlockOrigin.", + "message": "கேள்விகளுக்கான பதில்கள் மற்றும் பிற வகையான உதவி ஆதரவு /r/uBlockOrigin என்ற சப்ரெடிட்டில் வழங்கப்படுகிறது.", "description": "First paragraph of 'Questions and support' section in Support pane" }, "supportS3H": { - "message": "Filter issues/website is broken", + "message": "வடிப்பான் சிக்கல்கள்/இணையதளம் செயலிழந்துள்ளது", "description": "Header of 'Filter issues' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "குறிப்பிட்ட இணையதளங்களில் உள்ள வடிப்பான் சிக்கல்களை uBlockOrigin/uAssets சிக்கல் கண்காணிப்பாளரிடம் புகாரளிக்கவும். GitHub கணக்கு தேவை.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS3P2": { - "message": "Important: Avoid using other similarly-purposed blockers along with uBlock Origin, as this may cause filter issues on specific websites.", + "message": "முக்கியமானது: uBlock Origin உடன் இதே போன்ற நோக்கத்தில் உள்ள பிற தடுப்பான்களைப் பயன்படுத்துவதைத் தவிர்க்கவும், ஏனெனில் இது குறிப்பிட்ட இணையதளங்களில் வடிப்பான் சிக்கல்களை ஏற்படுத்தலாம்.", "description": "Second paragraph of 'Filter issues' section in Support pane" }, "supportS3P3": { - "message": "Tips: Be sure your filter lists are up to date. The logger is the primary tool to diagnose filter-related issues.", + "message": "உதவிக்குறிப்புகள்: உங்கள் வடிப்பான் பட்டியல்கள் புதுப்பித்த நிலையில் இருப்பதை உறுதிசெய்யவும். பதிவு கருவி வடிப்பான் தொடர்பான சிக்கல்களைக் கண்டறிவதற்கான முதன்மைக் கருவியாகும்.", "description": "Third paragraph of 'Filter issues' section in Support pane" }, "supportS4H": { @@ -944,7 +944,7 @@ "description": "Header of 'Bug report' section in Support pane" }, "supportS4P1": { - "message": "Report issues with uBlock Origin itself to the uBlockOrigin/uBlock-issue issue tracker. Requires a GitHub account.", + "message": "uBlock Origin உடன் தொடர்புடைய சிக்கல்களை uBlockOrigin/uBlock-issue சிக்கல் கண்காணிப்பாளரிடம் புகாரளிக்கவும். GitHub கணக்கு தேவை.", "description": "First paragraph of 'Bug report' section in Support pane" }, "supportS5H": { @@ -952,7 +952,7 @@ "description": "Header of 'Troubleshooting Information' section in Support pane" }, "supportS5P1": { - "message": "Below is technical information that might be useful when volunteers are trying to help you solve a problem.", + "message": "தன்னார்வலர்கள் உங்களுக்கு ஒரு சிக்கலைத் தீர்க்க உதவ முயற்சிக்கும்போது பயனுள்ளதாக இருக்கும் தொழில்நுட்பத் தகவல் கீழே உள்ளது.", "description": "First paragraph of 'Troubleshooting Information' section in Support pane" }, "supportS6H": { @@ -960,15 +960,15 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "தன்னார்வலர்களுக்கு நகல் அறிக்கைகளால் சுமையை ஏற்படுத்துவதைத் தவிர்க்க, இந்த சிக்கல் ஏற்கனவே புகாரளிக்கப்படவில்லை என்பதை உறுதிசெய்யவும். குறிப்பு: பொத்தானைக் கிளிக் செய்வதால் பக்கத்தின் மூல (origin) GitHub க்கு அனுப்பப்படும்.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { - "message": "Filter lists are updated daily. Be sure your issue has not already been addressed in the most recent filter lists.", + "message": "வடிப்பான் பட்டியல்கள் தினமும் புதுப்பிக்கப்படும். உங்கள் சிக்கல் சமீபத்திய வடிப்பான் பட்டியல்களில் ஏற்கனவே தீர்க்கப்படவில்லை என்பதை உறுதிசெய்யவும்.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S2": { - "message": "Verify that the issue still exists after reloading the problematic web page.", + "message": "சிக்கலுள்ள இணையப் பக்கத்தை மீண்டும் ஏற்றிய பிறகு சிக்கல் இன்னும் உள்ளதா என்பதை சரிபார்க்கவும்.", "description": "A paragraph in the filter issue reporter section" }, "supportS6URL": { @@ -980,19 +980,19 @@ "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- ஒரு உள்ளீட்டைத் தேர்வு செய்யவும் --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "விளம்பரங்கள் அல்லது விளம்பர எச்சங்களைக் காட்டுகிறது", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "மேலோட்டங்கள் (overlays) அல்லது பிற தொல்லைகள் உள்ளன", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBlock Origin", + "message": "uBlock Origin ஐ கண்டறிகிறது", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { @@ -1008,11 +1008,11 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "தீம்பொருள், பிஷிங் போன்றவற்றிற்கு இட்டுச்செல்கிறது", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "இணையப் பக்கத்தை “NSFW” (“பணிக்கு பாதுகாப்பானது அல்ல”) என்று பெயரிடவும்", "description": "A checkbox to use for NSFW sites" }, "aboutPrivacyPolicy": { @@ -1156,7 +1156,7 @@ "description": "English: Close this window" }, "docblockedDontWarn": { - "message": "Don't warn me again about this site", + "message": "இந்த தளத்தைப் பற்றி மீண்டும் என்னை எச்சரிக்க வேண்டாம்", "description": "Label for checkbox in document-blocked page" }, "docblockedProceed": { @@ -1176,7 +1176,7 @@ "description": "Button text to navigate to the blocked page" }, "docblockedRedirectPrompt": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "தடுக்கப்பட்ட பக்கம் வேறொரு தளத்திற்கு திருப்பிவிட முயல்கிறது. நீங்கள் தொடர்ந்து செல்ல தேர்வுசெய்தால், நீங்கள் நேரடியாக இங்கு செல்லுவீர்கள்: {{url}}", "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { @@ -1184,7 +1184,7 @@ "description": "The label which prepend the actual reason why a page was blocked" }, "docblockedReasonMalicious": { - "message": "Malicious", + "message": "தீங்கிழைக்கும்", "description": "An actual reason why a page was blocked" }, "docblockedReasonTracker": { @@ -1248,7 +1248,7 @@ "description": "A context menu entry, present when large media elements have been blocked on the current site" }, "contextMenuViewSource": { - "message": "View source code…", + "message": "மூலக் குறியீட்டைக் காண்க…", "description": "A context menu entry, to view the source code of the target resource" }, "shortcutCapturePlaceholder": { @@ -1272,7 +1272,7 @@ "description": "Label for keyboard shortcut used to toggle cosmetic filtering" }, "toggleJavascript": { - "message": "Toggle JavaScript", + "message": "JavaScript ஐ மாற்று", "description": "Label for keyboard shortcut used to toggle no-scripting switch" }, "relaxBlockingMode": { @@ -1304,7 +1304,7 @@ "description": "Summary of number of errors as reported by the linter " }, "unprocessedRequestTooltip": { - "message": "Could not filter properly at browser launch. Reload the page to ensure proper filtering.", + "message": "உலாவி தொடக்கத்தில் சரியாக வடிகட்ட முடியவில்லை. சரியான வடிகட்டலை உறுதிசெய்ய பக்கத்தை மீண்டும் ஏற்றவும்.", "description": "A warning which will appear in the popup panel if needed" }, "dummy": { diff --git a/src/_locales/te/messages.json b/src/_locales/te/messages.json index 5b4414c3708a2..bd9fccd91eb13 100644 --- a/src/_locales/te/messages.json +++ b/src/_locales/te/messages.json @@ -16,7 +16,7 @@ "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "ఉండు", + "message": "ఇక్కడే ఉండండి", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { @@ -484,11 +484,11 @@ "description": "Filter lists section name" }, "3pGroupSocial": { - "message": "Social widgets", + "message": "సామాజిక విడ్జెట్లు", "description": "Filter lists section name" }, "3pGroupCookies": { - "message": "Cookie notices", + "message": "కుకీ నోటీసులు", "description": "Filter lists section name" }, "3pGroupAnnoyances": { @@ -540,11 +540,11 @@ "description": "Warning against copy-pasting filters from random sources" }, "1pEnableMyFiltersLabel": { - "message": "Enable my custom filters", + "message": "నా అనుకూల ఫిల్టర్లను ప్రారంభించండి", "description": "Label for the checkbox use to enable/disable 'My filters' list" }, "1pTrustMyFiltersLabel": { - "message": "Allow custom filters requiring trust", + "message": "విశ్వాసం అవసరమయ్యే అనుకూల ఫిల్టర్లను అనుమతించండి", "description": "Label for the checkbox use to trust the content of 'My filters' list" }, "1pImport": { @@ -920,87 +920,87 @@ "description": "Header of 'Questions and support' section in Support pane" }, "supportS2P1": { - "message": "Answers to questions and other kinds of help support is provided on the subreddit /r/uBlockOrigin.", + "message": "ప్రశ్నలకు సమాధానాలు మరియు ఇతర రకాల సహాయ మద్దతు /r/uBlockOrigin సబ్రెడిట్‌లో అందించబడుతుంది.", "description": "First paragraph of 'Questions and support' section in Support pane" }, "supportS3H": { - "message": "Filter issues/website is broken", + "message": "ఫిల్టర్ సమస్యలు/వెబ్‌సైట్ పనిచేయడం లేదు", "description": "Header of 'Filter issues' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "నిర్దిష్ట వెబ్‌సైట్లతో ఫిల్టర్ సమస్యలను uBlockOrigin/uAssets ఇష్యూ ట్రాకర్‌కు నివేదించండి. GitHub ఖాతా అవసరం.", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS3P2": { - "message": "Important: Avoid using other similarly-purposed blockers along with uBlock Origin, as this may cause filter issues on specific websites.", + "message": "ముఖ్యం: uBlock Originతో పాటు ఇతర సారూప్య ప్రయోజనాల బ్లాకర్లను ఉపయోగించడం మానుకోండి, ఎందుకంటే ఇది నిర్దిష్ట వెబ్‌సైట్లలో ఫిల్టర్ సమస్యలకు కారణం కావచ్చు.", "description": "Second paragraph of 'Filter issues' section in Support pane" }, "supportS3P3": { - "message": "Tips: Be sure your filter lists are up to date. The logger is the primary tool to diagnose filter-related issues.", + "message": "చిట్కాలు: మీ ఫిల్టర్ జాబితాలు తాజాగా ఉన్నాయని నిర్ధారించుకోండి. లాగర్ ఫిల్టర్-సంబంధిత సమస్యలను నిర్ధారించడానికి ప్రాథమిక సాధనం.", "description": "Third paragraph of 'Filter issues' section in Support pane" }, "supportS4H": { - "message": "Bug report", + "message": "బగ్ నివేదిక", "description": "Header of 'Bug report' section in Support pane" }, "supportS4P1": { - "message": "Report issues with uBlock Origin itself to the uBlockOrigin/uBlock-issue issue tracker. Requires a GitHub account.", + "message": "uBlock Originతో సంబంధించిన సమస్యలను uBlockOrigin/uBlock-issue ఇష్యూ ట్రాకర్‌కు నివేదించండి. GitHub ఖాతా అవసరం.", "description": "First paragraph of 'Bug report' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting Information", + "message": "సమస్య పరిష్కార సమాచారం", "description": "Header of 'Troubleshooting Information' section in Support pane" }, "supportS5P1": { - "message": "Below is technical information that might be useful when volunteers are trying to help you solve a problem.", + "message": "క్రింద సాంకేతిక సమాచారం ఉంది, ఇది స్వచ్ఛంద సేవకులు మీ సమస్యను పరిష్కరించడానికి ప్రయత్నిస్తున్నప్పుడు ఉపయోగపడవచ్చు.", "description": "First paragraph of 'Troubleshooting Information' section in Support pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "ఫిల్టర్ సమస్యను నివేదించండి", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "నకిలీ నివేదికలతో స్వచ్ఛంద సేవకులకు భారం కలగకుండా ఉండటానికి, సమస్య ఇప్పటికే నివేదించబడలేదని ధృవీకరించండి. గమనిక: బటన్‌ను క్లిక్ చేయడం వలన పేజీ యొక్క మూలం GitHubకు పంపబడుతుంది.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { - "message": "Filter lists are updated daily. Be sure your issue has not already been addressed in the most recent filter lists.", + "message": "ఫిల్టర్ జాబితాలు ప్రతిరోజూ నవీకరించబడతాయి. మీ సమస్య ఇటీవలి ఫిల్టర్ జాబితాలలో ఇప్పటికే పరిష్కరించబడలేదని నిర్ధారించుకోండి.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S2": { - "message": "Verify that the issue still exists after reloading the problematic web page.", + "message": "సమస్యాత్మక వెబ్ పేజీని తిరిగి లోడ్ చేసిన తర్వాత సమస్య ఇప్పటికీ ఉందని ధృవీకరించండి.", "description": "A paragraph in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "వెబ్ పేజీ చిరునామా:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "వెబ్ పేజీ…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- ఒక ఎంపికను ఎంచుకోండి --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "ప్రకటనలు లేదా ప్రకటన అవశేషాలను చూపిస్తుంది", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "ఓవర్లేలు లేదా ఇతర అసౌకర్యాలు ఉన్నాయి", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBlock Origin", + "message": "uBlock Originను గుర్తిస్తుంది", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "గోప్యత-సంబంధిత సమస్యలు ఉన్నాయి", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBlock Origin is enabled", + "message": "uBlock Origin ప్రారంభించబడినప్పుడు పనిచేయకపోవడం", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { @@ -1008,7 +1008,7 @@ "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "చెడు సాఫ్ట్‌వేర్, ఫిషింగ్‌కు దారితీస్తుంది", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { @@ -1156,7 +1156,7 @@ "description": "English: Close this window" }, "docblockedDontWarn": { - "message": "Don't warn me again about this site", + "message": "ఈ సైట్ గురించి మళ్ళీ నాకు హెచ్చరించవద్దు", "description": "Label for checkbox in document-blocked page" }, "docblockedProceed": { @@ -1172,27 +1172,27 @@ "description": "English: Permanently" }, "docblockedDisable": { - "message": "Proceed", + "message": "కొనసాగించండి", "description": "Button text to navigate to the blocked page" }, "docblockedRedirectPrompt": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "నిరోధించబడిన పేజీ మరొక సైట్‌కు దారి మళ్ళించాలనుకుంటుంది. మీరు కొనసాగించాలని ఎంచుకుంటే, మీరు నేరుగా ఇక్కడికి నావిగేట్ చేస్తారు: {{url}}", "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { - "message": "Reason:", + "message": "కారణం:", "description": "The label which prepend the actual reason why a page was blocked" }, "docblockedReasonMalicious": { - "message": "Malicious", + "message": "హానికరమైనది", "description": "An actual reason why a page was blocked" }, "docblockedReasonTracker": { - "message": "Tracker", + "message": "ట్రాకర్", "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { - "message": "Disreputable", + "message": "ప్రతిష్ట లేని", "description": "An actual reason why a page was blocked" }, "cloudPush": { @@ -1248,7 +1248,7 @@ "description": "A context menu entry, present when large media elements have been blocked on the current site" }, "contextMenuViewSource": { - "message": "View source code…", + "message": "సోర్స్ కోడ్ చూడండి…", "description": "A context menu entry, to view the source code of the target resource" }, "shortcutCapturePlaceholder": { @@ -1264,15 +1264,15 @@ "description": "Label for buttons used to copy something to the clipboard" }, "genericSelectAll": { - "message": "Select all", + "message": "అన్నీ ఎంచుకోండి", "description": "Label for buttons used to select all text in editor" }, "toggleCosmeticFiltering": { - "message": "Toggle cosmetic filtering", + "message": "కాస్మెటిక్ ఫిల్టరింగ్‌ను టోగుల్ చేయండి", "description": "Label for keyboard shortcut used to toggle cosmetic filtering" }, "toggleJavascript": { - "message": "Toggle JavaScript", + "message": "జావాస్క్రిప్ట్‌ను టోగుల్ చేయండి", "description": "Label for keyboard shortcut used to toggle no-scripting switch" }, "relaxBlockingMode": { @@ -1300,11 +1300,11 @@ "description": "Message used in frame placeholders" }, "linterMainReport": { - "message": "Errors: {{count}}", + "message": "లోపాలు: {{count}}", "description": "Summary of number of errors as reported by the linter " }, "unprocessedRequestTooltip": { - "message": "Could not filter properly at browser launch. Reload the page to ensure proper filtering.", + "message": "బ్రౌజర్ ప్రారంభంలో సరిగ్గా ఫిల్టర్ చేయలేకపోయింది. సరైన ఫిల్టరింగ్ కోసం పేజీని తిరిగి లోడ్ చేయండి.", "description": "A warning which will appear in the popup panel if needed" }, "dummy": { diff --git a/src/_locales/th/messages.json b/src/_locales/th/messages.json index 20c4bb1d09c0d..aa461a763a42d 100644 --- a/src/_locales/th/messages.json +++ b/src/_locales/th/messages.json @@ -16,7 +16,7 @@ "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "อยู่ต่อ", + "message": "พักที่นี่", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "กฏเว็บเดียว: คอลัมน์นี้มีไว้สําหรับกฏบนเว็บไซต์นี้เท่านั้น\nกฏเว็บเดียวจะถูกใช้งานก่อนกฏครอบคลุม", + "message": "กฏเว็บเดียว: คอลัมน์นี้มีไว้สําหรับกฏบนเว็บไซต์นี้เท่านั้น", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -480,7 +480,7 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "Malware domains", + "message": "การป้องกันมัลแวร์, ความปลอดภัย", "description": "Filter lists section name" }, "3pGroupSocial": { diff --git a/src/_locales/tr/messages.json b/src/_locales/tr/messages.json index b74076ba48d69..1bf0b467de0dc 100644 --- a/src/_locales/tr/messages.json +++ b/src/_locales/tr/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Yerel kurallar: bu sütun yalnızca geçerli siteye uygulanan kurallar içindir.\nYerel kurallar genel kuralları geçersiz kılar.", + "message": "Yerel kurallar: Bu sütun yalnızca geçerli siteye uygulanan kurallar içindir.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { diff --git a/src/_locales/uk/messages.json b/src/_locales/uk/messages.json index 21a8867f68cd9..66fc9da4d7834 100644 --- a/src/_locales/uk/messages.json +++ b/src/_locales/uk/messages.json @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Локальні правила: цей стовпчик для правил, що застосовуються лише цього сайту.\nЛокальні правила замінюють глобальні.", + "message": "Локальні правила: цей стовпчик для правил, що застосовуються лише цього сайту.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -528,7 +528,7 @@ "description": "used as a tooltip for the clock icon beside a list" }, "3pUpdating": { - "message": "Оновлюється...", + "message": "Оновлюється…", "description": "used as a tooltip for the spinner icon beside a list" }, "3pNetworkError": { @@ -960,7 +960,7 @@ "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "Щоб не обтяжувати волонтерів повторюваними звітами, переконайтеся, що про проблему ще не повідомлялося.", + "message": "Щоб не обтяжувати волонтерів повторюваними звітами, переконайтеся, що про проблему ще не повідомлялося.Зауваження: натискання на кнопку призведе до надсилання походження сторінки на GitHub.", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { @@ -976,7 +976,7 @@ "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "Вебсторінка...", + "message": "Вебсторінка…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { @@ -1240,7 +1240,7 @@ "description": "An entry in the browser's contextual menu" }, "contextMenuSubscribeToList": { - "message": "Підписатися на список фільтрів...", + "message": "Підписатися на список фільтрів…", "description": "An entry in the browser's contextual menu" }, "contextMenuTemporarilyAllowLargeMediaElements": { @@ -1248,7 +1248,7 @@ "description": "A context menu entry, present when large media elements have been blocked on the current site" }, "contextMenuViewSource": { - "message": "Перегляд джерела...", + "message": "Перегляд джерела…", "description": "A context menu entry, to view the source code of the target resource" }, "shortcutCapturePlaceholder": { diff --git a/src/_locales/ur/messages.json b/src/_locales/ur/messages.json index 36a32c74a371f..de2c95de41472 100644 --- a/src/_locales/ur/messages.json +++ b/src/_locales/ur/messages.json @@ -12,7 +12,7 @@ "description": "English: uBlock₀ — Dashboard" }, "dashboardUnsavedWarning": { - "message": "خبردار! آپ نے محفوظ نہیں کیا", + "message": "! خبردار! آپ نے محفوظ نہیں کیا!", "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { @@ -104,11 +104,11 @@ "description": "For the new mobile-friendly popup design" }, "popupBlockedSinceInstall_v2": { - "message": "Blocked since install", + "message": "انسٹال کے بعد سے مسدود", "description": "For the new mobile-friendly popup design" }, "popupDomainsConnected_v2": { - "message": "Domains connected", + "message": "منسلک ڈومینز", "description": "For the new mobile-friendly popup design" }, "popupTipDashboard": { @@ -128,7 +128,7 @@ "description": "Tooltip used for the logger icon in the panel" }, "popupTipReport": { - "message": "Report an issue on this website", + "message": "اس ویب سائٹ پر مسئلہ رپورٹ کریں", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipNoPopups": { @@ -188,23 +188,23 @@ "description": "Tooltip for the no-scripting per-site switch" }, "popupNoPopups_v2": { - "message": "Pop-up windows", + "message": "پاپ اپ ونڈوز", "description": "Caption for the no-popups per-site switch" }, "popupNoLargeMedia_v2": { - "message": "Large media elements", + "message": "بڑے میڈیا عناصر", "description": "Caption for the no-large-media per-site switch" }, "popupNoCosmeticFiltering_v2": { - "message": "Cosmetic filtering", + "message": "کاسمیٹک فلٹرنگ", "description": "Caption for the no-cosmetic-filtering per-site switch" }, "popupNoRemoteFonts_v2": { - "message": "Remote fonts", + "message": "ریموٹ فونٹس", "description": "Caption for the no-remote-fonts per-site switch" }, "popupNoScripting_v2": { - "message": "JavaScript", + "message": "جاوا اسکرپٹ", "description": "Caption for the no-scripting per-site switch" }, "popupMoreButton_v2": { @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "مقامی اصول: اس کالم میں وہ اصول ہیں جو صرف موجودہ سائٹ پر لاگو ہوں گے.\nمقامی اصول کو گلوبل اصولوں پر ترجیح دی جائے گی.", + "message": "مقامی اصول: اس کالم میں وہ اصول ہیں جو صرف موجودہ سائٹ پر لاگو ہوں گے.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -264,23 +264,23 @@ "description": "" }, "popupHitDomainCountPrompt": { - "message": "domains connected", + "message": "منسلک ڈومینز", "description": "appears in popup" }, "popupHitDomainCount": { - "message": "{{count}} out of {{total}}", + "message": "{{count}} میں سے {{total}}", "description": "appears in popup" }, "popupVersion": { - "message": "Version", + "message": "ورژن", "description": "Example of use: Version 1.26.4" }, "popup3pScriptFilter": { - "message": "script", + "message": "اسکرپٹ", "description": "Appears as an option to filter out firewall rows" }, "popup3pFrameFilter": { - "message": "frame", + "message": "فریم", "description": "Appears as an option to filter out firewall rows" }, "pickerCreate": { @@ -328,63 +328,63 @@ "description": "A checkbox in the Settings pane" }, "settingsContextMenuPrompt": { - "message": "Make use of context menu where appropriate", + "message": "جہاں مناسب ہو سیاق و سباق کے مینو کا استعمال کریں", "description": "English: Make use of context menu where appropriate" }, "settingsColorBlindPrompt": { - "message": "Color-blind friendly", + "message": "رنگ اندھوں کے لیے موزوں", "description": "English: Color-blind friendly" }, "settingsAppearance": { - "message": "Appearance", + "message": "ظاہری شکل", "description": "Section for controlling user interface appearance" }, "settingsThemeLabel": { - "message": "Theme", + "message": "تھیم", "description": "Label for checkbox to enable a custom dark theme" }, "settingsThemeAccent0Label": { - "message": "Custom accent color", + "message": "اپنی مرضی کا نمایاں رنگ", "description": "Label for checkbox to pick an accent color" }, "settingsCloudStorageEnabledPrompt": { - "message": "Enable cloud storage support", + "message": "کلاؤڈ اسٹوریج کی معاونت کو فعال کریں", "description": "" }, "settingsAdvancedUserPrompt": { - "message": "I am an advanced user", + "message": "میں ایک ماہر صارف ہوں", "description": "Checkbox to let user access advanced, technical features" }, "settingsPrefetchingDisabledPrompt": { - "message": "Disable pre-fetching (to prevent any connection for blocked network requests)", + "message": "پری فیچنگ کو غیر فعال کریں (مسدود نیٹ ورک کی درخواستوں کے لیے کسی بھی کنکشن کو روکنے کے لیے)", "description": "English: " }, "settingsHyperlinkAuditingDisabledPrompt": { - "message": "Disable hyperlink auditing", + "message": "ہائپر لنک آڈیٹنگ کو غیر فعال کریں", "description": "English: " }, "settingsWebRTCIPAddressHiddenPrompt": { - "message": "Prevent WebRTC from leaking local IP addresses", + "message": "WebRTC کو مقامی IP پتوں کے رساؤ سے روکیں", "description": "English: " }, "settingPerSiteSwitchGroup": { - "message": "Default behavior", + "message": "پہلے سے طے شدہ رویہ", "description": "" }, "settingPerSiteSwitchGroupSynopsis": { - "message": "These default behaviors can be overridden on a per-site basis", + "message": "ان پہلے سے طے شدہ رویوں کو فی سائٹ بنیادوں پر تبدیل کیا جا سکتا ہے", "description": "" }, "settingsNoCosmeticFilteringPrompt": { - "message": "Disable cosmetic filtering", + "message": "کاسمیٹک فلٹرنگ کو غیر فعال کریں", "description": "" }, "settingsNoLargeMediaPrompt": { - "message": "Block media elements larger than {{input}} KB", + "message": "{{input}} KB سے بڑے میڈیا عناصر کو مسدود کریں", "description": "" }, "settingsNoRemoteFontsPrompt": { - "message": "Block remote fonts", + "message": "ریموٹ فونٹس کو مسدود کریں", "description": "" }, "settingsNoScriptingPrompt": { @@ -392,19 +392,19 @@ "description": "The default state for the per-site no-scripting switch" }, "settingsNoCSPReportsPrompt": { - "message": "Block CSP reports", + "message": "CSP رپورٹس کو مسدود کریں", "description": "background information: https://github.com/gorhill/uBlock/issues/3150" }, "settingsUncloakCnamePrompt": { - "message": "Uncloak canonical names", + "message": "معیاری ناموں کو ظاہر کریں", "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" }, "settingsAdvanced": { - "message": "Advanced", + "message": "اعلیٰ", "description": "Section for controlling advanced-user settings" }, "settingsAdvancedSynopsis": { - "message": "Features suitable only for technical users", + "message": "خصوصیات جو صرف تکنیکی صارفین کے لیے موزوں ہیں", "description": "Description of section controlling advanced-user settings" }, "settingsAdvancedUserSettings": { @@ -420,15 +420,15 @@ "description": "English: Last backup:" }, "3pListsOfBlockedHostsPrompt": { - "message": "{{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:", + "message": "{{netFilterCount}} نیٹ ورک فلٹرز + {{cosmeticFilterCount}} کاسمیٹک فلٹرز از:", "description": "Appears at the top of the _3rd-party filters_ pane" }, "3pListsOfBlockedHostsPerListStats": { - "message": "{{used}} used out of {{total}}", + "message": "{{total}} میں سے {{used}} استعمال شدہ", "description": "Appears aside each filter list in the _3rd-party filters_ pane" }, "3pAutoUpdatePrompt1": { - "message": "Auto-update filter lists", + "message": "فلٹر لسٹوں کو خودکار اپ ڈیٹ کریں", "description": "A checkbox in the _3rd-party filters_ pane" }, "3pUpdateNow": { @@ -436,27 +436,27 @@ "description": "A button in the in the _3rd-party filters_ pane" }, "3pPurgeAll": { - "message": "Purge all caches", + "message": "تمام کیشے صاف کریں", "description": "A button in the in the _3rd-party filters_ pane" }, "3pParseAllABPHideFiltersPrompt1": { - "message": "Parse and enforce cosmetic filters", + "message": "کاسمیٹک فلٹرز کو پارس اور نافذ کریں", "description": "English: Parse and enforce Adblock+ element hiding filters." }, "3pParseAllABPHideFiltersInfo": { - "message": "Cosmetic filters serve to hide elements in a web page which are deemed to be a visual nuisance, and which can't be blocked by the network request-based filtering engines.", + "message": "کاسمیٹک فلٹرز ویب صفحے میں ان عناصر کو چھپانے کے لیے استعمال ہوتے ہیں جو بصری پریشانی کا باعث سمجھے جاتے ہیں، اور جنہیں نیٹ ورک کی درخواست پر مبنی فلٹرنگ انجنوں کے ذریعے مسدود نہیں کیا جا سکتا۔", "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." }, "3pIgnoreGenericCosmeticFilters": { - "message": "Ignore generic cosmetic filters", + "message": "عام کاسمیٹک فلٹرز کو نظر انداز کریں", "description": "This will cause uBO to ignore all generic cosmetic filters." }, "3pIgnoreGenericCosmeticFiltersInfo": { - "message": "Generic cosmetic filters are those cosmetic filters which are meant to apply on all web sites. Enabling this option will eliminate the memory and CPU overhead added to web pages as a result of handling generic cosmetic filters.\n\nIt is recommended to enable this option on less powerful devices.", + "message": "عام کاسمیٹک فلٹرز وہ کاسمیٹک فلٹرز ہیں جو تمام ویب سائٹس پر لاگو ہونے کے لیے ہیں۔ اس آپشن کو فعال کرنے سے عام کاسمیٹک فلٹرز کو ہینڈل کرنے کے نتیجے میں ویب صفحات پر شامل میموری اور سی پی یو کے بوجھ کو ختم کر دیا جائے گا۔\n\nکم طاقت والے آلات پر اس آپشن کو فعال کرنے کی سفارش کی جاتی ہے۔", "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." }, "3pSuspendUntilListsAreLoaded": { - "message": "Suspend network activity until all filter lists are loaded", + "message": "تمام فلٹر لسٹوں کے لوڈ ہونے تک نیٹ ورک کی سرگرمی معطل کریں", "description": "A checkbox in the 'Filter lists' pane" }, "3pListsOfBlockedHostsHeader": { @@ -464,11 +464,11 @@ "description": "English: Lists of blocked hosts" }, "3pApplyChanges": { - "message": "Apply changes", + "message": "تبدیلیاں لاگو کریں", "description": "English: Apply changes" }, "3pGroupDefault": { - "message": "Built-in", + "message": "بلٹ ان", "description": "Filter lists section name" }, "3pGroupAds": { @@ -480,23 +480,23 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "Malware protection, security", + "message": "مالویئر تحفظ، سیکیورٹی", "description": "Filter lists section name" }, "3pGroupSocial": { - "message": "Social widgets", + "message": "سوشل ویجٹس", "description": "Filter lists section name" }, "3pGroupCookies": { - "message": "Cookie notices", + "message": "کوکی نوٹسز", "description": "Filter lists section name" }, "3pGroupAnnoyances": { - "message": "Annoyances", + "message": "پریشانیاں", "description": "Filter lists section name" }, "3pGroupMultipurpose": { - "message": "Multipurpose", + "message": "کثیر المقاصد", "description": "Filter lists section name" }, "3pGroupRegions": { @@ -512,19 +512,19 @@ "description": "The label for the checkbox used to import external filter lists" }, "3pExternalListsHint": { - "message": "One URL per line. Invalid URLs will be silently ignored.", + "message": "ایک URL فی لائن۔ غلط URLs کو خاموشی سے نظر انداز کر دیا جائے گا۔", "description": "Short information about how to use the textarea to import external filter lists by URL" }, "3pExternalListObsolete": { - "message": "Out of date.", + "message": "پرانا ہے۔", "description": "used as a tooltip for the out-of-date icon beside a list" }, "3pViewContent": { - "message": "view content", + "message": "مواد دیکھیں", "description": "used as a tooltip for eye icon beside a list" }, "3pLastUpdate": { - "message": "Last update: {{ago}}.\nClick to force an update.", + "message": "آخری اپ ڈیٹ: {{ago}}۔\nاپ ڈیٹ کرنے کے لیے کلک کریں۔", "description": "used as a tooltip for the clock icon beside a list" }, "3pUpdating": { @@ -532,23 +532,23 @@ "description": "used as a tooltip for the spinner icon beside a list" }, "3pNetworkError": { - "message": "A network error prevented the resource from being updated.", + "message": "نیٹ ورک کی خرابی کی وجہ سے وسائل کو اپ ڈیٹ نہیں کیا جا سکا۔", "description": "used as a tooltip for error icon beside a list" }, "1pTrustWarning": { - "message": "Do not add filters from untrusted sources.", + "message": "ناقابل اعتماد ذرائع سے فلٹرز شامل نہ کریں۔", "description": "Warning against copy-pasting filters from random sources" }, "1pEnableMyFiltersLabel": { - "message": "Enable my custom filters", + "message": "میرے حسب ضرورت فلٹرز کو فعال کریں", "description": "Label for the checkbox use to enable/disable 'My filters' list" }, "1pTrustMyFiltersLabel": { - "message": "Allow custom filters requiring trust", + "message": "ایسے حسب ضرورت فلٹرز کی اجازت دیں جن پر بھروسہ درکار ہو", "description": "Label for the checkbox use to trust the content of 'My filters' list" }, "1pImport": { - "message": "Import and append…", + "message": "درآمد کریں اور منسلک کریں…", "description": "Button in the 'My filters' pane" }, "1pExport": { @@ -556,11 +556,11 @@ "description": "Button in the 'My filters' pane" }, "1pExportFilename": { - "message": "my-ublock-static-filters_{{datetime}}.txt", + "message": "میرے-ublock-جامد-فلٹرز_{{datetime}}.txt", "description": "English: my-ublock-static-filters_{{datetime}}.txt" }, "1pApplyChanges": { - "message": "Apply changes", + "message": "تبدیلیاں لاگو کریں", "description": "English: Apply changes" }, "rulesPermanentHeader": { @@ -572,11 +572,11 @@ "description": "header" }, "rulesRevert": { - "message": "Revert", + "message": "واپس جائیں", "description": "This will remove all temporary rules" }, "rulesCommit": { - "message": "Commit", + "message": "محفوظ کریں", "description": "This will persist temporary rules" }, "rulesEdit": { @@ -600,39 +600,39 @@ "description": "Button in the 'My rules' pane" }, "rulesDefaultFileName": { - "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "message": "میرے-ublock-متحرک-قواعد_{{datetime}}.txt", "description": "default file name to use" }, "rulesHint": { - "message": "List of your dynamic filtering rules.", + "message": "آپ کے متحرک فلٹرنگ قواعد کی فہرست۔", "description": "English: List of your dynamic filtering rules." }, "rulesFormatHint": { - "message": "Rule syntax: source destination type action (full documentation).", + "message": "قاعدہ نحو: ماخذ منزل قسم عمل (مکمل دستاویزات)۔", "description": "English: dynamic rule syntax and full documentation." }, "rulesSort": { - "message": "Sort:", + "message": "ترتیب دیں:", "description": "English: label for sort option." }, "rulesSortByType": { - "message": "Rule type", + "message": "قاعدہ کی قسم", "description": "English: a sort option for list of rules." }, "rulesSortBySource": { - "message": "Source", + "message": "ماخذ", "description": "English: a sort option for list of rules." }, "rulesSortByDestination": { - "message": "Destination", + "message": "منزل", "description": "English: a sort option for list of rules." }, "whitelistPrompt": { - "message": "The trusted site directives dictate on which web pages uBlock Origin should be disabled. One entry per line.", + "message": "قابل اعتماد سائٹ کی ہدایات بتاتی ہیں کہ کن ویب صفحات پر uBlock Origin کو غیر فعال کیا جانا چاہیے۔ ایک اندراج فی لائن۔", "description": "A concise description of the 'Trusted sites' pane." }, "whitelistImport": { - "message": "Import and append…", + "message": "درآمد کریں اور منسلک کریں…", "description": "Button in the 'Trusted sites' pane" }, "whitelistExport": { @@ -640,7 +640,7 @@ "description": "Button in the 'Trusted sites' pane" }, "whitelistExportFilename": { - "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "message": "میرے-ublock-قابل-اعتماد-سائٹس_{{datetime}}.txt", "description": "The default filename to use for import/export purpose" }, "whitelistApply": { @@ -668,7 +668,7 @@ "description": "Appears in the logger's tab selector" }, "logBehindTheScene": { - "message": "Tabless", + "message": "ٹیب کے بغیر", "description": "Pretty name for behind-the-scene network requests" }, "loggerCurrentTab": { @@ -676,43 +676,43 @@ "description": "Appears in the logger's tab selector" }, "loggerReloadTip": { - "message": "Reload the tab content", + "message": "ٹیب کا مواد دوبارہ لوڈ کریں", "description": "Tooltip for the reload button in the logger page" }, "loggerDomInspectorTip": { - "message": "Toggle the DOM inspector", + "message": "DOM انسپیکٹر کو ٹوگل کریں", "description": "Tooltip for the DOM inspector button in the logger page" }, "loggerPopupPanelTip": { - "message": "Toggle the popup panel", + "message": "پاپ اپ پینل کو ٹوگل کریں", "description": "Tooltip for the popup panel button in the logger page" }, "loggerInfoTip": { - "message": "uBlock Origin wiki: The logger", + "message": "uBlock Origin وکی: لاگر", "description": "Tooltip for the top-right info label in the logger page" }, "loggerClearTip": { - "message": "Clear logger", + "message": "لاگر صاف کریں", "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" }, "loggerPauseTip": { - "message": "Pause logger (discard all incoming data)", + "message": "لاگر کو روکیں (تمام آنے والے ڈیٹا کو ضائع کریں)", "description": "Tooltip for the pause button in the logger page" }, "loggerUnpauseTip": { - "message": "Unpause logger", + "message": "لاگر کو جاری کریں", "description": "Tooltip for the play button in the logger page" }, "loggerRowFiltererButtonTip": { - "message": "Toggle logger filtering", + "message": "لاگر فلٹرنگ کو ٹوگل کریں", "description": "Tooltip for the row filterer button in the logger page" }, "logFilterPrompt": { - "message": "filter logger content", + "message": "لاگر مواد کو فلٹر کریں", "description": "Placeholder string for logger output filtering input field" }, "loggerRowFiltererBuiltinTip": { - "message": "Logger filtering options", + "message": "لاگر فلٹرنگ کے اختیارات", "description": "Tooltip for the button to bring up logger output filtering options" }, "loggerRowFiltererBuiltinNot": { @@ -732,7 +732,7 @@ "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltinModified": { - "message": "modified", + "message": "ترمیم شدہ", "description": "A keyword in the built-in row filtering expression" }, "loggerRowFiltererBuiltin1p": { @@ -764,11 +764,11 @@ "description": "Label to identify a context field (typically a hostname)" }, "loggerEntryDetailsRootContext": { - "message": "Root context", + "message": "بنیادی سیاق و سباق", "description": "Label to identify a root context field (typically a hostname)" }, "loggerEntryDetailsPartyness": { - "message": "Partyness", + "message": "فریقیت", "description": "Label to identify a field providing partyness information" }, "loggerEntryDetailsType": { @@ -780,7 +780,7 @@ "description": "Label to identify the URL of an entry" }, "loggerURLFilteringHeader": { - "message": "URL rule", + "message": "URL قاعدہ", "description": "Small header to identify the dynamic URL filtering section" }, "loggerURLFilteringContextLabel": { @@ -792,11 +792,11 @@ "description": "Label for the type selector" }, "loggerStaticFilteringHeader": { - "message": "Static filter", + "message": "جامد فلٹر", "description": "Small header to identify the static filtering section" }, "loggerStaticFilteringSentence": { - "message": "{{action}} network requests of {{type}} {{br}}which URL address matches {{url}} {{br}}and which originates {{origin}},{{br}}{{importance}} there is a matching exception filter.", + "message": "{{action}} نیٹ ورک درخواستیں {{type}} {{br}}جن کا URL ایڈریس {{url}} سے مماثل ہے {{br}}اور جو {{origin}} سے شروع ہوتی ہیں،{{br}}{{importance}} ایک مماثل استثنائی فلٹر موجود ہے۔", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartBlock": { @@ -824,39 +824,39 @@ "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartNotImportant": { - "message": "except when", + "message": "سوائے اس کے کہ", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartImportant": { - "message": "even if", + "message": "چاہے", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringFinderSentence1": { - "message": "Static filter {{filter}} found in:", + "message": "جامد فلٹر {{filter}} اس میں پایا گیا:", "description": "Below this sentence, the filter list(s) in which the filter was found" }, "loggerStaticFilteringFinderSentence2": { - "message": "Static filter could not be found in any of the currently enabled filter lists", + "message": "جامد فلٹر موجودہ طور پر فعال فلٹر لسٹوں میں سے کسی میں نہیں پایا جا سکا", "description": "Message to show when a filter cannot be found in any filter lists" }, "loggerSettingDiscardPrompt": { - "message": "Logger entries which do not fulfill all three conditions below will be automatically discarded:", + "message": "لاگر اندراجات جو ذیل میں دی گئی تینوں شرائط پوری نہیں کرتے خودکار طور پر ضائع کر دیے جائیں گے:", "description": "Logger setting: A sentence to describe the purpose of the settings below" }, "loggerSettingPerEntryMaxAge": { - "message": "Preserve entries from the last {{input}} minutes", + "message": "گزشتہ {{input}} منٹ کے اندراجات کو محفوظ رکھیں", "description": "A logger setting" }, "loggerSettingPerTabMaxLoads": { - "message": "Preserve at most {{input}} page loads per tab", + "message": "فی ٹیب زیادہ سے زیادہ {{input}} صفحہ لوڈز کو محفوظ رکھیں", "description": "A logger setting" }, "loggerSettingPerTabMaxEntries": { - "message": "Preserve at most {{input}} entries per tab", + "message": "فی ٹیب زیادہ سے زیادہ {{input}} اندراجات کو محفوظ رکھیں", "description": "A logger setting" }, "loggerSettingPerEntryLineCount": { - "message": "Use {{input}} lines per entry in vertically expanded mode", + "message": "عمودی طور پر پھیلی ہوئی حالت میں فی اندراج {{input}} لائنیں استعمال کریں", "description": "A logger setting" }, "loggerSettingHideColumnsPrompt": { @@ -872,11 +872,11 @@ "description": "A label for the filter or rule column" }, "loggerSettingHideColumnContext": { - "message": "{{input}} Context", + "message": "{{input}} سیاق و سباق", "description": "A label for the context column" }, "loggerSettingHideColumnPartyness": { - "message": "{{input}} Partyness", + "message": "{{input}} فریقیت", "description": "A label for the partyness column" }, "loggerExportFormatList": { @@ -888,199 +888,199 @@ "description": "Label for radio-button to pick export format" }, "loggerExportEncodePlain": { - "message": "Plain", + "message": "سادہ", "description": "Label for radio-button to pick export text format" }, "loggerExportEncodeMarkdown": { - "message": "Markdown", + "message": "مارک ڈاؤن", "description": "Label for radio-button to pick export text format" }, "supportOpenButton": { - "message": "Open", + "message": "کھولیں", "description": "Text for button which open an external web page in Support pane" }, "supportReportSpecificButton": { - "message": "Create new report on GitHub", + "message": "GitHub پر نئی رپورٹ بنائیں", "description": "Text for button which open an external web page in Support pane" }, "supportFindSpecificButton": { - "message": "Find similar reports on GitHub", + "message": "GitHub پر مماثل رپورٹیں تلاش کریں", "description": "A clickable link in the filter issue reporter section" }, "supportS1H": { - "message": "Documentation", + "message": "دستاویزات", "description": "Header of 'Documentation' section in Support pane" }, "supportS1P1": { - "message": "Read the documentation at uBlock/wiki to learn about all of uBlock Origin's features.", + "message": "uBlock Origin کی تمام خصوصیات کے بارے میں جاننے کے لیے uBlock/wiki پر دستاویزات پڑھیں۔", "description": "First paragraph of 'Documentation' section in Support pane" }, "supportS2H": { - "message": "Questions and support", + "message": "سوالات اور مدد", "description": "Header of 'Questions and support' section in Support pane" }, "supportS2P1": { - "message": "Answers to questions and other kinds of help support is provided on the subreddit /r/uBlockOrigin.", + "message": "سوالات کے جوابات اور دیگر قسم کی مدد کی معاونت سب ریڈٹ /r/uBlockOrigin پر فراہم کی جاتی ہے۔", "description": "First paragraph of 'Questions and support' section in Support pane" }, "supportS3H": { - "message": "Filter issues/website is broken", + "message": "فلٹر کے مسائل/ویب سائٹ ٹوٹی ہوئی ہے", "description": "Header of 'Filter issues' section in Support pane" }, "supportS3P1": { - "message": "Report filter issues with specific websites to the uBlockOrigin/uAssets issue tracker. Requires a GitHub account.", + "message": "مخصوص ویب سائٹس کے ساتھ فلٹر کے مسائل کو uBlockOrigin/uAssets ایشو ٹریکر کو رپورٹ کریں۔ GitHub اکاؤنٹ درکار ہے۔", "description": "First paragraph of 'Filter issues' section in Support pane" }, "supportS3P2": { - "message": "Important: Avoid using other similarly-purposed blockers along with uBlock Origin, as this may cause filter issues on specific websites.", + "message": "اہم: uBlock Origin کے ساتھ دیگر اسی طرح کے مقاصد کے بلاکرز استعمال کرنے سے گریز کریں، کیونکہ اس سے مخصوص ویب سائٹس پر فلٹر کے مسائل پیدا ہو سکتے ہیں۔", "description": "Second paragraph of 'Filter issues' section in Support pane" }, "supportS3P3": { - "message": "Tips: Be sure your filter lists are up to date. The logger is the primary tool to diagnose filter-related issues.", + "message": "تجاویز: یقینی بنائیں کہ آپ کی فلٹر لسٹیں تازہ ترین ہیں۔ لاگر فلٹر سے متعلق مسائل کی تشخیص کا بنیادی ٹول ہے۔", "description": "Third paragraph of 'Filter issues' section in Support pane" }, "supportS4H": { - "message": "Bug report", + "message": "بگ رپورٹ", "description": "Header of 'Bug report' section in Support pane" }, "supportS4P1": { - "message": "Report issues with uBlock Origin itself to the uBlockOrigin/uBlock-issue issue tracker. Requires a GitHub account.", + "message": "خود uBlock Origin کے ساتھ مسائل کو uBlockOrigin/uBlock-issue ایشو ٹریکر کو رپورٹ کریں۔ GitHub اکاؤنٹ درکار ہے۔", "description": "First paragraph of 'Bug report' section in Support pane" }, "supportS5H": { - "message": "Troubleshooting Information", + "message": "خرابیوں کا ازالہ کرنے کی معلومات", "description": "Header of 'Troubleshooting Information' section in Support pane" }, "supportS5P1": { - "message": "Below is technical information that might be useful when volunteers are trying to help you solve a problem.", + "message": "ذیل میں تکنیکی معلومات ہے جو اس وقت کارآمد ہو سکتی ہے جب رضاکار آپ کو کسی مسئلے کو حل کرنے میں مدد کرنے کی کوشش کر رہے ہوں۔", "description": "First paragraph of 'Troubleshooting Information' section in Support pane" }, "supportS6H": { - "message": "Report a filter issue", + "message": "فلٹر کا مسئلہ رپورٹ کریں", "description": "Header of 'Report a filter issue' section in Support pane" }, "supportS6P1S1": { - "message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported. Note: clicking the button will cause the page's origin to be sent to GitHub.", + "message": "رضاکاروں کو نقلی رپورٹوں سے بوجھل کرنے سے بچنے کے لیے، براہ کرم تصدیق کریں کہ مسئلہ پہلے سے رپورٹ نہیں کیا گیا ہے۔ نوٹ: بٹن پر کلک کرنے سے صفحے کا ماخذ GitHub کو بھیج دیا جائے گا۔", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S1": { - "message": "Filter lists are updated daily. Be sure your issue has not already been addressed in the most recent filter lists.", + "message": "فلٹر لسٹیں روزانہ اپ ڈیٹ ہوتی ہیں۔ یقینی بنائیں کہ آپ کا مسئلہ تازہ ترین فلٹر لسٹوں میں پہلے سے حل نہیں کیا گیا ہے۔", "description": "A paragraph in the filter issue reporter section" }, "supportS6P2S2": { - "message": "Verify that the issue still exists after reloading the problematic web page.", + "message": "مشکل والے ویب صفحے کو دوبارہ لوڈ کرنے کے بعد تصدیق کریں کہ مسئلہ اب بھی موجود ہے۔", "description": "A paragraph in the filter issue reporter section" }, "supportS6URL": { - "message": "Address of the web page:", + "message": "ویب صفحے کا پتہ:", "description": "Label for the URL of the page" }, "supportS6Select1": { - "message": "The web page…", + "message": "ویب صفحہ…", "description": "Label for widget to select type of issue" }, "supportS6Select1Option0": { - "message": "-- Pick an entry --", + "message": "-- ایک اندراج منتخب کریں --", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option1": { - "message": "Shows ads or ad leftovers", + "message": "اشتہارات یا اشتہارات کی باقیات دکھاتا ہے", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option2": { - "message": "Has overlays or other nuisances", + "message": "اوورلے یا دیگر پریشانیاں ہیں", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option3": { - "message": "Detects uBlock Origin", + "message": "uBlock Origin کا پتہ لگاتا ہے", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option4": { - "message": "Has privacy-related issues", + "message": "رازداری سے متعلق مسائل ہیں", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option5": { - "message": "Malfunctions when uBlock Origin is enabled", + "message": "جب uBlock Origin فعال ہو تو خرابی پیدا کرتا ہے", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option6": { - "message": "Opens unwanted tabs or windows", + "message": "نادیدہ ٹیبز یا ونڈوز کھولتا ہے", "description": "An entry in the widget used to select the type of issue" }, "supportS6Select1Option7": { - "message": "Leads to badware, phishing", + "message": "بیڈویئر، فشنگ کی طرف لے جاتا ہے", "description": "An entry in the widget used to select the type of issue" }, "supportS6Checkbox1": { - "message": "Label the web page as “NSFW” (“Not Safe For Work”)", + "message": "ویب صفحے کو “NSFW” کا لیبل لگائیں (“Not Safe For Work”)", "description": "A checkbox to use for NSFW sites" }, "aboutPrivacyPolicy": { - "message": "Privacy policy", + "message": "رازداری کی پالیسی", "description": "Link to privacy policy on GitHub (English)" }, "aboutChangelog": { - "message": "Changelog", + "message": "تبدیلی لاگ", "description": "" }, "aboutCode": { - "message": "Source code (GPLv3)", + "message": "سورس کوڈ (GPLv3)", "description": "English: Source code (GPLv3)" }, "aboutContributors": { - "message": "Contributors", + "message": "تعاون کنندگان", "description": "English: Contributors" }, "aboutSourceCode": { - "message": "Source code", + "message": "سورس کوڈ", "description": "Link text to source code repo" }, "aboutTranslations": { - "message": "Translations", + "message": "ترجمے", "description": "Link text to translations repo" }, "aboutFilterLists": { - "message": "Filter lists", + "message": "فلٹر لسٹیں", "description": "Link text to uBO's own filter lists repo" }, "aboutDependencies": { - "message": "External dependencies (GPLv3-compatible):", + "message": "خارجی انحصارات (GPLv3-مطابق):", "description": "Shown in the About pane" }, "aboutCDNs": { - "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "message": "uBO کی اپنی فلٹر لسٹیں درج ذیل CDNs پر مفت میزبانی کرتی ہیں:", "description": "Shown in the About pane" }, "aboutCDNsInfo": { - "message": "A randomly picked CDN is used when a filter list needs to be updated.", + "message": "جب فلٹر لسٹ کو اپ ڈیٹ کرنے کی ضرورت ہوتی ہے تو بے ترتیب طور پر منتخب کردہ CDN استعمال کیا جاتا ہے۔", "description": "Shown in the About pane" }, "aboutBackupDataButton": { - "message": "Back up to file…", + "message": "فائل میں بیک اپ کریں…", "description": "Text for button to create a backup of all settings" }, "aboutBackupFilename": { - "message": "my-ublock-backup_{{datetime}}.txt", + "message": "میرے-ublock-بیک اپ_{{datetime}}.txt", "description": "English: my-ublock-backup_{{datetime}}.txt" }, "aboutRestoreDataButton": { - "message": "Restore from file…", + "message": "فائل سے بحال کریں…", "description": "English: Restore from file..." }, "aboutResetDataButton": { - "message": "Reset to default settings…", + "message": "پہلے سے طے شدہ ترتیبات پر ری سیٹ کریں…", "description": "English: Reset to default settings..." }, "aboutRestoreDataConfirm": { - "message": "All your settings will be overwritten using data backed up on {{time}}, and uBlock₀ will restart.\n\nOverwrite all existing settings using backed up data?", + "message": "آپ کی تمام ترتیبات {{time}} کو بیک اپ کیے گئے ڈیٹا کا استعمال کرتے ہوئے تبدیل کر دی جائیں گی، اور uBlock₀ دوبارہ شروع ہو جائے گا۔\n\nکیا بیک اپ ڈیٹا کا استعمال کرتے ہوئے تمام موجودہ ترتیبات کو تبدیل کیا جائے؟", "description": "Message asking user to confirm restore" }, "aboutRestoreDataError": { - "message": "The data could not be read or is invalid", + "message": "ڈیٹا پڑھا نہیں جا سکا یا غلط ہے", "description": "Message to display when an error occurred during restore" }, "aboutResetDataConfirm": { - "message": "All your settings will be removed, and uBlock₀ will restart.\n\nReset uBlock₀ to factory settings?", + "message": "آپ کی تمام ترتیبات ہٹا دی جائیں گی، اور uBlock₀ دوبارہ شروع ہو جائے گا۔\n\nکیا uBlock₀ کو فیکٹری ترتیبات پر ری سیٹ کیا جائے؟", "description": "Message asking user to confirm reset" }, "errorCantConnectTo": { @@ -1088,7 +1088,7 @@ "description": "English: Network error: {{msg}}" }, "subscribeButton": { - "message": "Subscribe", + "message": "سبسکرائب کریں", "description": "For the button used to subscribe to a filter list" }, "elapsedOneMinuteAgo": { @@ -1120,7 +1120,7 @@ "description": "Firefox/Fennec-specific: Show Dashboard" }, "showNetworkLogButton": { - "message": "Show Logger", + "message": "لاگر دکھائیں", "description": "Firefox/Fennec-specific: Show Logger" }, "fennecMenuItemBlockingOff": { @@ -1128,23 +1128,23 @@ "description": "Firefox-specific: appears as 'uBlock₀ (off)'" }, "docblockedTitle": { - "message": "Page blocked", + "message": "صفحہ مسدود ہے", "description": "Used as a title for the document-blocked page" }, "docblockedPrompt1": { - "message": "uBlock Origin has prevented the following page from loading:", + "message": "uBlock Origin نے درج ذیل صفحہ کو لوڈ ہونے سے روک دیا ہے:", "description": "Used in the strict-blocking page" }, "docblockedPrompt2": { - "message": "This happened because of the following filter:", + "message": "یہ درج ذیل فلٹر کی وجہ سے ہوا:", "description": "Used in the strict-blocking page" }, "docblockedNoParamsPrompt": { - "message": "without parameters", + "message": "پیرامیٹرز کے بغیر", "description": "label to be used for the parameter-less URL: https://cloud.githubusercontent.com/assets/585534/9832014/bfb1b8f0-593b-11e5-8a27-fba472a5529a.png" }, "docblockedFoundIn": { - "message": "The filter has been found in:", + "message": "فلٹر اس میں پایا گیا ہے:", "description": "English: List of filter list names follows" }, "docblockedBack": { @@ -1156,11 +1156,11 @@ "description": "English: Close this window" }, "docblockedDontWarn": { - "message": "Don't warn me again about this site", + "message": "مجھے اس سائٹ کے بارے میں دوبارہ خبردار نہ کریں", "description": "Label for checkbox in document-blocked page" }, "docblockedProceed": { - "message": "Disable strict blocking for {{hostname}}", + "message": "{{hostname}} کے لیے سخت بلاکنگ کو غیر فعال کریں", "description": "English: Disable strict blocking for {{hostname}} ..." }, "docblockedDisableTemporary": { @@ -1172,27 +1172,27 @@ "description": "English: Permanently" }, "docblockedDisable": { - "message": "Proceed", + "message": "آگے بڑھیں", "description": "Button text to navigate to the blocked page" }, "docblockedRedirectPrompt": { - "message": "The blocked page wants to redirect to another site. If you choose to proceed, you will navigate directly to: {{url}}", + "message": "مسدود صفحہ کسی دوسری سائٹ پر ری ڈائریکٹ کرنا چاہتا ہے۔ اگر آپ آگے بڑھنے کا انتخاب کرتے ہیں، تو آپ براہ راست اس پر تشریف لے جائیں گے: {{url}}", "description": "Text warning about an incoming redirect" }, "docblockedReasonLabel": { - "message": "Reason:", + "message": "وجہ:", "description": "The label which prepend the actual reason why a page was blocked" }, "docblockedReasonMalicious": { - "message": "Malicious", + "message": "نقصان دہ", "description": "An actual reason why a page was blocked" }, "docblockedReasonTracker": { - "message": "Tracker", + "message": "ٹریکر", "description": "An actual reason why a page was blocked" }, "docblockedReasonDisreputable": { - "message": "Disreputable", + "message": "بدنام", "description": "An actual reason why a page was blocked" }, "cloudPush": { @@ -1216,7 +1216,7 @@ "description": "used as a prompt for the user to provide a custom device name" }, "advancedSettingsWarning": { - "message": "Warning! Change these advanced settings at your own risk.", + "message": "انتباہ! ان اعلیٰ ترتیبات کو اپنی ذمہ داری پر تبدیل کریں۔", "description": "A warning to users at the top of 'Advanced settings' page" }, "genericSubmit": { @@ -1232,31 +1232,31 @@ "description": "for generic 'Revert' buttons" }, "genericBytes": { - "message": "bytes", + "message": "بائٹس", "description": "" }, "contextMenuBlockElementInFrame": { - "message": "Block element in frame…", + "message": "فریم میں عنصر کو مسدود کریں…", "description": "An entry in the browser's contextual menu" }, "contextMenuSubscribeToList": { - "message": "Subscribe to filter list…", + "message": "فلٹر لسٹ کو سبسکرائب کریں…", "description": "An entry in the browser's contextual menu" }, "contextMenuTemporarilyAllowLargeMediaElements": { - "message": "Temporarily allow large media elements", + "message": "بڑے میڈیا عناصر کو عارضی طور پر اجازت دیں", "description": "A context menu entry, present when large media elements have been blocked on the current site" }, "contextMenuViewSource": { - "message": "View source code…", + "message": "سورس کوڈ دیکھیں…", "description": "A context menu entry, to view the source code of the target resource" }, "shortcutCapturePlaceholder": { - "message": "Type a shortcut", + "message": "شارٹ کٹ ٹائپ کریں", "description": "Placeholder string for input field used to capture a keyboard shortcut" }, "genericMergeViewScrollLock": { - "message": "Toggle locked scrolling", + "message": "تالا بند اسکرولنگ کو ٹوگل کریں", "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" }, "genericCopyToClipboard": { @@ -1264,23 +1264,23 @@ "description": "Label for buttons used to copy something to the clipboard" }, "genericSelectAll": { - "message": "Select all", + "message": "سب کو منتخب کریں", "description": "Label for buttons used to select all text in editor" }, "toggleCosmeticFiltering": { - "message": "Toggle cosmetic filtering", + "message": "کاسمیٹک فلٹرنگ کو ٹوگل کریں", "description": "Label for keyboard shortcut used to toggle cosmetic filtering" }, "toggleJavascript": { - "message": "Toggle JavaScript", + "message": "جاوا اسکرپٹ کو ٹوگل کریں", "description": "Label for keyboard shortcut used to toggle no-scripting switch" }, "relaxBlockingMode": { - "message": "Relax blocking mode", + "message": "بلاکنگ موڈ کو نرم کریں", "description": "Label for keyboard shortcut used to relax blocking mode" }, "storageUsed": { - "message": "Storage used: {{value}} {{unit}}", + "message": "استعمال شدہ اسٹوریج: {{value}} {{unit}}", "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" }, "KB": { @@ -1296,15 +1296,15 @@ "description": "short for 'gigabytes'" }, "clickToLoad": { - "message": "Click to load", + "message": "لوڈ کرنے کے لیے کلک کریں", "description": "Message used in frame placeholders" }, "linterMainReport": { - "message": "Errors: {{count}}", + "message": "خرابیاں: {{count}}", "description": "Summary of number of errors as reported by the linter " }, "unprocessedRequestTooltip": { - "message": "Could not filter properly at browser launch. Reload the page to ensure proper filtering.", + "message": "براؤزر کے آغاز پر صحیح طریقے سے فلٹر نہیں کر سکا۔ مناسب فلٹرنگ کو یقینی بنانے کے لیے صفحہ کو دوبارہ لوڈ کریں۔", "description": "A warning which will appear in the popup panel if needed" }, "dummy": { diff --git a/src/_locales/vi/messages.json b/src/_locales/vi/messages.json index b988fd373d255..9b09b9f0f1794 100644 --- a/src/_locales/vi/messages.json +++ b/src/_locales/vi/messages.json @@ -12,7 +12,7 @@ "description": "English: uBlock₀ — Dashboard" }, "dashboardUnsavedWarning": { - "message": "Cảnh báo! Bạn có các thay đổi chưa được lưu", + "message": "Cảnh báo: Bạn có các thay đổi chưa được lưu!", "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "Quy tắc nội bộ: cột này dành cho quy tắc chỉ áp dụng cho trang hiện tại.\nQuy tắc nội bộ sẽ thay thế quy tắc chung.", + "message": "Quy tắc nội bộ: cột này dành cho quy tắc chỉ áp dụng cho trang hiện tại.", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -512,7 +512,7 @@ "description": "The label for the checkbox used to import external filter lists" }, "3pExternalListsHint": { - "message": "Một URL mỗi dòng. URL không hợp lệ sẽ âm thầm bị bỏ qua.", + "message": "Một URL mỗi dòng. URL không hợp lệ sẽ âm thầm bỏ qua.", "description": "Short information about how to use the textarea to import external filter lists by URL" }, "3pExternalListObsolete": { @@ -528,7 +528,7 @@ "description": "used as a tooltip for the clock icon beside a list" }, "3pUpdating": { - "message": "Đang cập nhật...", + "message": "Đang cập nhật…", "description": "used as a tooltip for the spinner icon beside a list" }, "3pNetworkError": { @@ -904,7 +904,7 @@ "description": "Text for button which open an external web page in Support pane" }, "supportFindSpecificButton": { - "message": "Tìm các báo cáo tương tự", + "message": "Tìm các báo cáo tương tự trên Github", "description": "A clickable link in the filter issue reporter section" }, "supportS1H": { @@ -1048,7 +1048,7 @@ "description": "Shown in the About pane" }, "aboutCDNs": { - "message": "Danh sách các bộ lọc của riêng uBO được lưu trữ miễn phí tại các CDN sau:", + "message": "danh sách bộ lọc riêng của uBO được lưu trữ miễn phí trên CDNs:", "description": "Shown in the About pane" }, "aboutCDNsInfo": { @@ -1132,7 +1132,7 @@ "description": "Used as a title for the document-blocked page" }, "docblockedPrompt1": { - "message": "uBloc Origin đã chặn tải trang sau:", + "message": "uBlock Origin đã chặn tải trang sau:", "description": "Used in the strict-blocking page" }, "docblockedPrompt2": { diff --git a/src/_locales/zh_CN/messages.json b/src/_locales/zh_CN/messages.json index a06a37e051974..805e0991a71ca 100644 --- a/src/_locales/zh_CN/messages.json +++ b/src/_locales/zh_CN/messages.json @@ -16,7 +16,7 @@ "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { - "message": "留下", + "message": "留在这里", "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { @@ -68,7 +68,7 @@ "description": "Title for the advanced settings page" }, "popupPowerSwitchInfo": { - "message": "单击:对此网站禁用/启用 uBlock₀。\n\nCtrl + 单击:仅对此页面禁用 uBlock₀。", + "message": "单击:对此网站禁用/启用 uBlock₀ 。\n\nCtrl + 单击:仅在此页面上禁用 uBlock₀ 。", "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." }, "popupPowerSwitchInfo1": { @@ -220,7 +220,7 @@ "description": "Tooltip when hovering the top-most cell of the global-rules column." }, "popupTipLocalRules": { - "message": "本地规则:此列的规则仅作用于当前网站。\n本地规则优先于全局规则。", + "message": "本地规则:此列的规则仅作用于当前网站。", "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { @@ -404,7 +404,7 @@ "description": "Section for controlling advanced-user settings" }, "settingsAdvancedSynopsis": { - "message": "仅适合专家级用户的功能。", + "message": "仅适合专业用户的功能。", "description": "Description of section controlling advanced-user settings" }, "settingsAdvancedUserSettings": { @@ -480,7 +480,7 @@ "description": "Filter lists section name" }, "3pGroupMalware": { - "message": "恶意软件防护、安全", + "message": "恶意软件防护,安全", "description": "Filter lists section name" }, "3pGroupSocial": { @@ -488,7 +488,7 @@ "description": "Filter lists section name" }, "3pGroupCookies": { - "message": "Cookie提醒", + "message": "Cookie 提醒", "description": "Filter lists section name" }, "3pGroupAnnoyances": { @@ -512,7 +512,7 @@ "description": "The label for the checkbox used to import external filter lists" }, "3pExternalListsHint": { - "message": "一行一条网址。无效网址将被忽略。", + "message": "每行一个 URL。无效的 URL 将被忽略。", "description": "Short information about how to use the textarea to import external filter lists by URL" }, "3pExternalListObsolete": { @@ -680,7 +680,7 @@ "description": "Tooltip for the reload button in the logger page" }, "loggerDomInspectorTip": { - "message": "是否打开 DOM 探查器", + "message": "打开/关闭 DOM 检查器", "description": "Tooltip for the DOM inspector button in the logger page" }, "loggerPopupPanelTip": { @@ -744,7 +744,7 @@ "description": "A keyword in the built-in row filtering expression" }, "loggerEntryDetailsHeader": { - "message": "详细资料", + "message": "详情", "description": "Small header to identify the 'Details' pane for a specific logger entry" }, "loggerEntryDetailsFilter": { diff --git a/src/_locales/zh_TW/messages.json b/src/_locales/zh_TW/messages.json index c9ee02cf6d23b..4d6530266e213 100644 --- a/src/_locales/zh_TW/messages.json +++ b/src/_locales/zh_TW/messages.json @@ -12,7 +12,7 @@ "description": "English: uBlock₀ — Dashboard" }, "dashboardUnsavedWarning": { - "message": "警告!變更尚未儲存。", + "message": "警告:變更尚未儲存!", "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { @@ -40,11 +40,11 @@ "description": "appears as tab name in dashboard" }, "whitelistPageName": { - "message": "受信任網站", + "message": "白名單", "description": "appears as tab name in dashboard" }, "shortcutsPageName": { - "message": "快捷鍵", + "message": "快速鍵", "description": "appears as tab name in dashboard" }, "statsPageName": { @@ -128,7 +128,7 @@ "description": "Tooltip used for the logger icon in the panel" }, "popupTipReport": { - "message": "回報網站問題", + "message": "回報這個網站的問題", "description": "Tooltip used for the 'chat' icon in the panel" }, "popupTipNoPopups": { @@ -136,7 +136,7 @@ "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoPopups1": { - "message": "點擊以封鎖網站的所有彈出式視窗", + "message": "點擊以封鎖此網站的所有彈出型視窗", "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoPopups2": { @@ -176,11 +176,11 @@ "description": "Tooltip for the no-remote-fonts per-site switch" }, "popupTipNoRemoteFonts2": { - "message": "點擊以解除封鎖網站的遠端字型", + "message": "點擊以解除封鎖此網站的遠端字型", "description": "Tooltip for the no-remote-fonts per-site switch" }, "popupTipNoScripting1": { - "message": "點擊以停用網站的 JavaScript", + "message": "點擊以停用此網站的 JavaScript", "description": "Tooltip for the no-scripting per-site switch" }, "popupTipNoScripting2": { diff --git a/src/about.html b/src/about.html index e747a93051d2a..9c69c7250ebd9 100644 --- a/src/about.html +++ b/src/about.html @@ -41,6 +41,7 @@ +
diff --git a/src/css/codemirror.css b/src/css/codemirror.css index d56d8c0da1a13..f0bd4d26d6b4d 100644 --- a/src/css/codemirror.css +++ b/src/css/codemirror.css @@ -320,9 +320,12 @@ html:not(.mobile) .cm-search-widget .fa-icon:not(.fa-icon-ro):hover { .CodeMirror-lintmarker > * { position: absolute; } -.CodeMirror-lintmarker[data-error="y"] { +.CodeMirror-lintmarker[data-lint="error"] { background-color: var(--sf-error-ink); } +.CodeMirror-lintmarker[data-lint="warning"] { + background-color: var(--sf-warning-ink); + } .CodeMirror-lintmarker .msg { background-color: var(--surface-0); border: 1px solid var(--sf-error-ink); @@ -340,7 +343,8 @@ html:not(.mobile) .cm-search-widget .fa-icon:not(.fa-icon-ro):hover { top: 15%; width: 70%; } -.CodeMirror-lintmarker[data-error="y"] svg { +.CodeMirror-lintmarker[data-lint="error"] svg, +.CodeMirror-lintmarker[data-lint="warning"] svg { display: none; } .CodeMirror-lintmarker[data-fold="start"] { @@ -352,8 +356,10 @@ html:not(.mobile) .cm-search-widget .fa-icon:not(.fa-icon-ro):hover { .CodeMirror-lintmarker[data-fold="end"] { fill: var(--border-2); } -.CodeMirror-lintmarker[data-error="y"]:hover > span, -.CodeMirror-lintmarker[data-error="y"] > span:hover { +.CodeMirror-lintmarker[data-lint="error"]:hover > span, +.CodeMirror-lintmarker[data-lint="error"] > span:hover, +.CodeMirror-lintmarker[data-lint="warning"]:hover > span, +.CodeMirror-lintmarker[data-lint="warning"] > span:hover { display: initial; } diff --git a/src/css/logger-ui.css b/src/css/logger-ui.css index 38e434f56e37c..e37939625dba5 100644 --- a/src/css/logger-ui.css +++ b/src/css/logger-ui.css @@ -718,7 +718,7 @@ body[dir="rtl"] .netFilteringDialog > .panes > .details > div > span:nth-of-type flex-grow: 1; max-height: 10vh; overflow: hidden auto; - white-space: pre-line + white-space: pre-wrap; } .netFilteringDialog > .panes > .details > div > span:nth-of-type(2):not(.prose) { word-break: break-all; diff --git a/src/css/themes/default.css b/src/css/themes/default.css index 8a6378aa62124..d03e1f1231b49 100644 --- a/src/css/themes/default.css +++ b/src/css/themes/default.css @@ -290,7 +290,7 @@ --sf-unicode-ink: var(--ink-1); --sf-value-ink: #974900 /* h:30 S:100 Luv:40 */; --sf-variable-ink: var(--ink-1); - --sf-warning-ink: #e49d00; /* h:50 S:100 Luv:70 */ + --sf-warning-ink: #ffbb03; /* h:50 S:100 Luv:70 */ --sf-warning-surface: #e49d0033; /* h:50 S:100 Luv:70 @ 20% */ /* syntax highlight: dynamic filtering */ @@ -314,7 +314,7 @@ --elevation-up1-opacity: 12%; --elevation-up2-opacity: 24%; - --ink-rgb: var(--gray-95); + --ink-rgb: var(--gray-90); --ink-0: white; --ink-100: black; diff --git a/src/js/1p-filters.js b/src/js/1p-filters.js index 934acd466d17b..9396dd117979d 100644 --- a/src/js/1p-filters.js +++ b/src/js/1p-filters.js @@ -80,9 +80,9 @@ uBlockDashboard.patchCodeMirrorEditor(cmEditor); } vAPI.messaging.send('dashboard', { - what: 'getTrustedScriptletTokens', + what: 'getTrustedTokens', }).then(tokens => { - cmEditor.setOption('trustedScriptletTokens', tokens); + cmEditor.setOption('trustedTokens', tokens); }); /******************************************************************************/ diff --git a/src/js/asset-viewer.js b/src/js/asset-viewer.js index 62f90d2795013..697c468ed4e5f 100644 --- a/src/js/asset-viewer.js +++ b/src/js/asset-viewer.js @@ -73,9 +73,9 @@ import { dom, qs$ } from './dom.js'; }); vAPI.messaging.send('dashboard', { - what: 'getTrustedScriptletTokens', + what: 'getTrustedTokens', }).then(tokens => { - cmEditor.setOption('trustedScriptletTokens', tokens); + cmEditor.setOption('trustedTokens', tokens); }); const details = await vAPI.messaging.send('default', { diff --git a/src/js/codemirror/ubo-static-filtering.js b/src/js/codemirror/ubo-static-filtering.js index d188ab7d7464d..dcf128cb79856 100644 --- a/src/js/codemirror/ubo-static-filtering.js +++ b/src/js/codemirror/ubo-static-filtering.js @@ -23,6 +23,7 @@ /******************************************************************************/ +import '../../lib/regexanalyzer/regex.js'; import * as sfp from '../static-filtering-parser.js'; import { dom, qs$ } from '../dom.js'; import { tokenizableStrFromRegex } from '../regex-analyzer.js'; @@ -45,10 +46,10 @@ CodeMirror.defineOption('trustedSource', false, (cm, trusted) => { })); }); -CodeMirror.defineOption('trustedScriptletTokens', undefined, (cm, tokens) => { +CodeMirror.defineOption('trustedTokens', undefined, (cm, tokens) => { if ( tokens === undefined || tokens === null ) { return; } if ( typeof tokens[Symbol.iterator] !== 'function' ) { return; } - self.dispatchEvent(new CustomEvent('trustedScriptletTokens', { + self.dispatchEvent(new CustomEvent('trustedTokens', { detail: new Set(tokens), })); }); @@ -225,6 +226,7 @@ const uBOStaticFilteringMode = (( ) => { this.astParser = new sfp.AstFilterParser({ interactive: true, nativeCssHas: vAPI.webextFlavor.env.includes('native_css_has'), + canFilterResponseBody: vAPI.webextFlavor.env.includes('html_filtering'), }); this.astWalker = this.astParser.getWalker(); this.currentWalkerNode = 0; @@ -233,8 +235,8 @@ const uBOStaticFilteringMode = (( ) => { const { trusted } = ev.detail; this.astParser.options.trustedSource = trusted; }); - self.addEventListener('trustedScriptletTokens', ev => { - this.astParser.options.trustedScriptletTokens = ev.detail; + self.addEventListener('trustedTokens', ev => { + this.astParser.options.trustedTokens = ev.detail; }); } } @@ -345,6 +347,7 @@ function initHints() { const astParser = new sfp.AstFilterParser({ interactive: true, nativeCssHas: vAPI.webextFlavor.env.includes('native_css_has'), + canFilterResponseBody: vAPI.webextFlavor.env.includes('html_filtering'), }); const proceduralOperatorNames = new Map( Array.from(sfp.proceduralOperatorTokens) @@ -714,6 +717,7 @@ CodeMirror.registerHelper('fold', 'ubo-static-filtering', (( ) => { const astParser = new sfp.AstFilterParser({ interactive: true, nativeCssHas: vAPI.webextFlavor.env.includes('native_css_has'), + canFilterResponseBody: vAPI.webextFlavor.env.includes('html_filtering'), }); const changeset = []; @@ -759,6 +763,9 @@ CodeMirror.registerHelper('fold', 'ubo-static-filtering', (( ) => { case sfp.AST_ERROR_UNTRUSTED_SOURCE: msg = `${msg}: Filter requires trusted source`; break; + case sfp.AST_ERROR_CAPABILITY: + msg = `Filter unsupported on current platform`; + return { lint: 'warning', msg }; default: if ( astParser.isCosmeticFilter() && astParser.result.error ) { msg = `${msg}: ${astParser.result.error}`; @@ -818,6 +825,14 @@ CodeMirror.registerHelper('fold', 'ubo-static-filtering', (( ) => { '
', ], }, + 'warning': { + node: null, + html: [ + '
 ', + '', + '
', + ], + }, 'if-start': { node: null, html: [ @@ -962,8 +977,8 @@ CodeMirror.registerHelper('fold', 'ubo-static-filtering', (( ) => { }; const processDeletion = (doc, change) => { - let { from, to } = change; - doc.eachLine(from.line, to.line, lineHandle => { + const { from, to } = change; + doc.eachLine(from.line, to.line + (to.ch ? 1 : 0), lineHandle => { const marker = extractMarker(lineHandle); if ( marker === null ) { return; } if ( marker.dataset.error === 'y' ) { @@ -1115,8 +1130,8 @@ CodeMirror.registerHelper('fold', 'ubo-static-filtering', (( ) => { astParser.options.trustedSource = trusted; }); - self.addEventListener('trustedScriptletTokens', ev => { - astParser.options.trustedScriptletTokens = ev.detail; + self.addEventListener('trustedTokens', ev => { + astParser.options.trustedTokens = ev.detail; }); CodeMirror.defineInitHook(cm => { diff --git a/src/js/contentscript-extra.js b/src/js/contentscript-extra.js index cb056c30f781d..482cb62e54a02 100644 --- a/src/js/contentscript-extra.js +++ b/src/js/contentscript-extra.js @@ -45,6 +45,13 @@ const regexFromString = (s, exact = false) => { return new RegExp(exact ? `^${reStr}$` : reStr); }; +const triggerDOMChange = ( ) => { + if ( typeof vAPI !== 'object' ) { return; } + if ( vAPI === null ) { return; } + const filterer = vAPI.domFilterer && vAPI.domFilterer.proceduralFilterer; + filterer?.onDOMChanged([ null ]); +}; + // 'P' stands for 'Procedural' class PSelectorTask { @@ -63,6 +70,19 @@ class PSelectorVoidTask extends PSelectorTask { } } +class PSelectorContentTask extends PSelectorTask { + constructor(task) { + super(); + this.selector = task[1]; + } + transpose(node, output) { + const root = node.content; + if ( typeof root?.querySelectorAll !== 'function' ) { return; } + const nodes = root.querySelectorAll(this.selector); + output.push(...nodes); + } +} + class PSelectorHasTextTask extends PSelectorTask { constructor(task) { super(); @@ -146,13 +166,7 @@ class PSelectorMatchesMediaTask extends PSelectorTask { super(); this.mql = window.matchMedia(task[1]); if ( this.mql.media === 'not all' ) { return; } - this.mql.addEventListener('change', ( ) => { - if ( typeof vAPI !== 'object' ) { return; } - if ( vAPI === null ) { return; } - const filterer = vAPI.domFilterer && vAPI.domFilterer.proceduralFilterer; - if ( filterer instanceof Object === false ) { return; } - filterer.onDOMChanged([ null ]); - }); + this.mql.addEventListener('change', triggerDOMChange); } transpose(node, output) { if ( this.mql.matches === false ) { return; } @@ -166,12 +180,17 @@ class PSelectorMatchesPathTask extends PSelectorTask { this.needle = regexFromString( task[1].replace(/\P{ASCII}/gu, s => encodeURIComponent(s)) ); + if ( PSelectorMatchesPathTask.#listener ) { return; } + PSelectorMatchesPathTask.#listener = true; + if ( Boolean(self.navigation) === false ) { return; } + self.navigation.addEventListener('navigate', triggerDOMChange); } transpose(node, output) { if ( this.needle.test(self.location.pathname + self.location.search) ) { output.push(node); } } + static #listener; } class PSelectorMatchesPropTask extends PSelectorTask { @@ -280,6 +299,7 @@ class PSelectorShadowTask extends PSelectorTask { if ( PSelectorShadowTask.openOrClosedShadowRoot !== undefined ) { return PSelectorShadowTask.openOrClosedShadowRoot; } + const { chrome } = self; if ( typeof chrome === 'object' && chrome !== null ) { if ( chrome.dom instanceof Object ) { if ( typeof chrome.dom.openOrClosedShadowRoot === 'function' ) { @@ -365,7 +385,6 @@ PSelectorUpwardTask.prototype.s = ''; class PSelectorWatchAttrs extends PSelectorTask { constructor(task) { super(); - this.observer = null; this.observed = new WeakSet(); this.observerOptions = { attributes: true, @@ -376,23 +395,16 @@ class PSelectorWatchAttrs extends PSelectorTask { this.observerOptions.attributeFilter = task[1]; } } - // TODO: Is it worth trying to re-apply only the current selector? - handler() { - const filterer = - vAPI.domFilterer && vAPI.domFilterer.proceduralFilterer; - if ( filterer instanceof Object ) { - filterer.onDOMChanged([ null ]); - } - } transpose(node, output) { output.push(node); if ( this.observed.has(node) ) { return; } - if ( this.observer === null ) { - this.observer = new MutationObserver(this.handler); + if ( PSelectorWatchAttrs.#observer === undefined ) { + PSelectorWatchAttrs.#observer = new MutationObserver(triggerDOMChange); } - this.observer.observe(node, this.observerOptions); + PSelectorWatchAttrs.#observer.observe(node, this.observerOptions); this.observed.add(node); } + static #observer; } class PSelectorXpathTask extends PSelectorTask { @@ -476,6 +488,7 @@ class PSelector { } } PSelector.prototype.operatorToTaskMap = new Map([ + [ 'content', PSelectorContentTask ], [ 'has', PSelectorIfTask ], [ 'has-text', PSelectorHasTextTask ], [ 'if', PSelectorIfTask ], diff --git a/src/js/cosmetic-filtering.js b/src/js/cosmetic-filtering.js index 4b4e561d5612c..dcb3f8e5974ec 100644 --- a/src/js/cosmetic-filtering.js +++ b/src/js/cosmetic-filtering.js @@ -312,13 +312,15 @@ CosmeticFilteringEngine.prototype.compile = function(parser, writer) { // https://github.com/chrisaljoudi/uBlock/issues/151 // Negated hostname means the filter applies to all non-negated hostnames // of same filter OR globally if there is no non-negated hostnames. + const isException = parser.isException(); let applyGlobally = true; for ( const { hn, not, bad } of parser.getExtFilterDomainIterator() ) { if ( bad ) { continue; } if ( not === false ) { applyGlobally = false; } - this.compileSpecificSelector(parser, hn, not, writer); + if ( isException && not ) { continue; } + this.compileSpecificSelector(parser, hn, isException || not, writer); } if ( applyGlobally ) { this.compileGenericSelector(parser, writer); @@ -427,10 +429,10 @@ CosmeticFilteringEngine.prototype.compileGenericUnhideSelector = function( CosmeticFilteringEngine.prototype.compileSpecificSelector = function( parser, hostname, - not, + isException, writer ) { - const { raw, compiled, exception } = parser.result; + const { raw, compiled } = parser.result; if ( compiled === undefined ) { const who = writer.properties.get('name') || '?'; logger.writeOne({ @@ -442,7 +444,7 @@ CosmeticFilteringEngine.prototype.compileSpecificSelector = function( } writer.select('COSMETIC_FILTERS:SPECIFIC'); - const prefix = ((exception ? 1 : 0) ^ (not ? 1 : 0)) ? '-' : '+'; + const prefix = isException ? '-' : '+'; writer.push([ 8, hostname, `${prefix}${compiled}` ]); }; diff --git a/src/js/document-blocked.js b/src/js/document-blocked.js index a062c334c1e7e..999d0ca9ff1f6 100644 --- a/src/js/document-blocked.js +++ b/src/js/document-blocked.js @@ -41,11 +41,12 @@ const urlToFragment = raw => { try { const fragment = new DocumentFragment(); const url = new URL(raw); + const href = url.href; const hn = url.hostname; - const i = raw.indexOf(hn); + const i = href.indexOf(hn); const b = document.createElement('b'); b.append(hn); - fragment.append(raw.slice(0,i), b, raw.slice(i+hn.length)); + fragment.append(href.slice(0,i), b, href.slice(i+hn.length)); return fragment; } catch { } diff --git a/src/js/html-filtering.js b/src/js/html-filtering.js index 9b5a50465ea35..9557d0a256c2c 100644 --- a/src/js/html-filtering.js +++ b/src/js/html-filtering.js @@ -65,6 +65,19 @@ class PSelectorVoidTask { transpose() { } } + +class PSelectorContentTask { + constructor(task) { + this.selector = task[1]; + } + transpose(node, output) { + const root = node.content; + if ( typeof root?.querySelectorAll !== 'function' ) { return; } + const nodes = root.querySelectorAll(this.selector); + output.push(...nodes); + } +} + class PSelectorHasTextTask { constructor(task) { this.needle = regexFromString(task[1]); @@ -238,6 +251,7 @@ class PSelector { } } PSelector.prototype.operatorToTaskMap = new Map([ + [ 'content', PSelectorContentTask ], [ 'has', PSelectorIfTask ], [ 'has-text', PSelectorHasTextTask ], [ 'if', PSelectorIfTask ], @@ -329,7 +343,7 @@ htmlFilteringEngine.compile = function(parser, writer) { // Only exception filters are allowed to be global. if ( parser.hasOptions() === false ) { if ( isException ) { - writer.push([ 64, '', 1, compiled ]); + writer.push([ 64, '', `-${compiled}` ]); } return; } @@ -338,10 +352,11 @@ htmlFilteringEngine.compile = function(parser, writer) { let hasOnlyNegated = true; for ( const { hn, not, bad } of parser.getExtFilterDomainIterator() ) { if ( bad ) { continue; } - const prefix = ((isException ? 1 : 0) ^ (not ? 1 : 0)) ? '-' : '+'; if ( not === false ) { hasOnlyNegated = false; } + if ( isException && not ) { continue; } + const prefix = isException || not ? '-' : '+'; compiledFilters.push([ 64, hn, `${prefix}${compiled}` ]); } diff --git a/src/js/jsonpath.js b/src/js/jsonpath.js index 2369430a26c36..ec4207fa733ee 100644 --- a/src/js/jsonpath.js +++ b/src/js/jsonpath.js @@ -24,19 +24,14 @@ * Implement the parsing of uBO-flavored JSON path queries. * * Reference to original JSON path syntax: - * https://goessner.net/articles/JsonPath/index.html + * https://www.rfc-editor.org/info/rfc9535/ * * uBO-flavored JSON path implementation differs as follow: + * - Array slice operator not supported + * - Selectors can be a `/`-delimited regex, i.e. `$./pattern/` + * - Onle a single filter selector is allowed in filter selector syntax * - * - Both $ and @ are implicit. Though you can use them, you do not have to. - * Use $ only when the implicit context is not that of root. Example: - * - Official: $..book[?(@.isbn)] - * - uBO-flavored: ..book[?(.isbn)] - * - * - uBO-flavor syntax does not (yet) support: - * - Array slice operator - * - * - Regarding filter expressions, uBO-flavored JSON path supports a limited + * - uBO-flavored JSON path supports a limited set of filter selectors: * set of expressions since unlike the official implementation, uBO can't use * JS eval() to evaluate arbitrary JS expressions. The operand MUST be valid * JSON. The currently supported expressions are: @@ -49,8 +44,13 @@ * - ^=: stringified value starts with * - $=: stringified value ends with * - *=: stringified value includes - * - =/.../: regular expression matches + * - =/.../: true if the regular expression matches the stringified value * + * - uBO-flavored JSON path supports assignement operator: + * - =[any well-formed JSON value] + * - =repl(...): [to be documented] i.e. {"regex":"...","flags":"i","replacement":"..."} + * - =call(...): [to be documented] i.e. ["${obj}","setAttribute","${key}"] + * * * - Examples (from "JSONPath examples" at reference link) * - .store.book[*].author * - ..author @@ -85,6 +85,10 @@ export class JSONPath { return (stringifier || JSON.stringify)(obj, ...args) .replace(/\//g, '\\/'); } + static keys = Object.keys; + static entries = Object.entries; + static hasOwn = Object.hasOwn; + static Regex = RegExp; get value() { return this.#compiled && this.#compiled.rval; } @@ -97,14 +101,17 @@ export class JSONPath { } compile(query) { this.#compiled = undefined; + this.v2 = query.startsWith('v2:'); + if ( this.v2 ) { query = query.slice(3); } const r = this.#compile(query, 0); if ( r === undefined ) { return; } if ( r.i !== query.length ) { let val; if ( query.startsWith('=', r.i) ) { - if ( /^=repl\(.+\)$/.test(query.slice(r.i)) ) { - r.modify = 'repl'; - val = query.slice(r.i+6, -1); + const match = this.#reRval.exec(query.slice(r.i)); + if ( match ) { + r.modify = match[1]; + val = match[2]; } else { val = query.slice(r.i+1); } @@ -115,11 +122,12 @@ export class JSONPath { try { r.rval = JSON.parse(val); } catch { return; } } + r.v2 = this.v2; this.#compiled = r; } evaluate(root) { if ( this.valid === false ) { return []; } - this.#root = root; + this.#root = { '$': root }; const paths = this.#evaluate(this.#compiled.steps, []); this.#root = null; return paths; @@ -133,6 +141,7 @@ export class JSONPath { if ( i === 0 ) { this.#root = null; return; } while ( i-- ) { const { obj, key } = this.#resolvePath(paths[i]); + if ( obj === undefined ) { continue; } if ( rval !== undefined ) { this.#modifyVal(obj, key); } else if ( Array.isArray(obj) && typeof key === 'number' ) { @@ -159,9 +168,12 @@ export class JSONPath { #CURRENT = 2; #CHILDREN = 3; #DESCENDANTS = 4; + #QUANTIFIER = 5; #reUnquotedIdentifier = /^[A-Za-z_][\w]*|^\*/; - #reExpr = /^([!=^$*]=|[<>]=?)(.+?)\]/; + #reExpr = /^\s*([!=^$*]=|[<>]=?)\s*(.+?)\]/; #reIndice = /^-?\d+/; + #reRval = /^=([a-z]+)\((.+)\)$/; + #reQuantifier = /^\{(\d+|\d+,\d+|\d+,|,\d+)\};\$/; #root; #compiled; #compile(query, i) { @@ -197,24 +209,55 @@ export class JSONPath { } continue; } + if ( c === 0x3B /* ; */ ) { + if ( query.startsWith(';$', i) === false ) { return; } + steps.push( + { mv: this.#QUANTIFIER, min: 1, max: 1e6 }, + { mv: this.#ROOT } + ); + i += 2; + mv = this.#UNDEFINED; + continue; + } + if ( c === 0x7B /* { */ ) { + const match = this.#reQuantifier.exec(query.slice(i)); + if ( match === null ) { return; } + const comma = match[1].indexOf(','); + let min, max; + if ( comma === -1 ) { + min = max = parseInt(match[1]); + } else { + min = parseInt(match[1].slice(0, comma)) || 0; + max = parseInt(match[1].slice(comma+1)) || 1e6; + } + steps.push( + { mv: this.#QUANTIFIER, min, max }, + { mv: this.#ROOT } + ); + i += match[0].length; + mv = this.#UNDEFINED; + continue; + } if ( c !== 0x5B /* [ */ ) { if ( mv === this.#UNDEFINED ) { const step = steps.at(-1); if ( step === undefined ) { return; } - i = this.#compileExpr(query, step, i); + const j = this.#compileExpr(query, step, i); + if ( j ) { i = j; } break; } - const s = this.#consumeUnquotedIdentifier(query, i); - if ( s === undefined ) { return; } - steps.push({ mv, k: s }); - i += s.length; + const r = this.#consumeUnquotedIdentifier(query, i); + if ( r === undefined ) { return; } + steps.push({ mv, k: r.s }); + i = r.i; mv = this.#UNDEFINED; continue; } // Bracket accessor syntax + if ( mv === this.#CHILDREN ) { return; } if ( query.startsWith('[?', i) ) { - const not = query.charCodeAt(i+2) === 0x21 /* ! */; - const j = i + 2 + (not ? 1 : 0); + const not = query.charCodeAt(i+2) === 0x21 /* ! */ ? 1 : 0; + const j = i + 2 + not; const r = this.#compile(query, j); if ( r === undefined ) { return; } if ( query.startsWith(']', r.i) === false ) { return; } @@ -251,12 +294,26 @@ export class JSONPath { resultset = [ [ '$' ] ]; break; case this.#CURRENT: + if ( step.op ) { + const { obj, key } = this.#resolvePath(pathin); + if ( obj === undefined ) { return []; } + const outcome = this.#evaluateExpr(step, obj, key); + if ( outcome !== true ) { break; } + } resultset = [ pathin ]; break; case this.#CHILDREN: - case this.#DESCENDANTS: + case this.#DESCENDANTS: { + if ( resultset.length === 0 ) { break; } resultset = this.#getMatches(resultset, step); break; + } + case this.#QUANTIFIER: { + const { length } = resultset; + if ( length < step.min || length > step.max ) { return []; } + resultset = []; + break; + } default: break; } @@ -267,61 +324,72 @@ export class JSONPath { const listout = []; for ( const pathin of listin ) { const { value: owner } = this.#resolvePath(pathin); - if ( step.k === '*' ) { - this.#getMatchesFromAll(pathin, step, owner, listout); - } else if ( step.k !== undefined ) { - this.#getMatchesFromKeys(pathin, step, owner, listout); - } else if ( step.steps ) { + if ( owner === undefined ) { continue; } + if ( step.steps ) { this.#getMatchesFromExpr(pathin, step, owner, listout); + continue; + } + const iter = this.#expandKey(owner, step.k); + if ( iter ) { + for ( const k of iter ) { + const outcome = this.#evaluateExpr(step, owner, k); + if ( outcome !== true ) { continue; } + listout.push([ ...pathin, k ]); + } + } + if ( step.mv !== this.#DESCENDANTS ) { continue; } + for ( const { obj, key, path } of this.#getDescendants(owner, true) ) { + const iter = this.#expandKey(obj[key], step.k); + if ( iter === undefined ) { continue; } + for ( const k of iter ) { + const outcome = this.#evaluateExpr(step, obj[key], k); + if ( outcome !== true ) { continue; } + listout.push([ ...pathin, ...path, k ]); + } } } return listout; } - #getMatchesFromAll(pathin, step, owner, out) { - const recursive = step.mv === this.#DESCENDANTS; - for ( const { path } of this.#getDescendants(owner, recursive) ) { - out.push([ ...pathin, ...path ]); + #expandKey(owner, k) { + if ( typeof owner !== 'object' || owner === null ) { return; } + if ( Array.isArray(k) ) { + const out = []; + for ( const a of k ) { + const iter = this.#expandKey(owner, a); + if ( iter === undefined ) { continue; } + out.push(...iter); + } + return out; } - } - #getMatchesFromKeys(pathin, step, owner, out) { - const kk = Array.isArray(step.k) ? step.k : [ step.k ]; - for ( const k of kk ) { - const normalized = this.#evaluateExpr(step, owner, k); - if ( normalized === undefined ) { continue; } - out.push([ ...pathin, normalized ]); + if ( typeof k === 'number' ) { + if ( Array.isArray(owner) === false ) { return; } + return [ k >= 0 ? k : owner.length + k ]; } - if ( step.mv !== this.#DESCENDANTS ) { return; } - for ( const { obj, key, path } of this.#getDescendants(owner, true) ) { - for ( const k of kk ) { - const normalized = this.#evaluateExpr(step, obj[key], k); - if ( normalized === undefined ) { continue; } - out.push([ ...pathin, ...path, normalized ]); + if ( k === '*' ) { + if ( Array.isArray(owner) ) { return owner.keys(); } + return JSONPath.keys(owner); + } + if ( k instanceof JSONPath.Regex ) { + const out = []; + for ( const key of JSONPath.keys(owner) ) { + if ( k.test(key) === false ) { continue; } + out.push(key); } + return out; } + return [ k ]; } #getMatchesFromExpr(pathin, step, owner, out) { const recursive = step.mv === this.#DESCENDANTS; - if ( Array.isArray(owner) === false ) { - const r = this.#evaluate(step.steps, pathin); - if ( r.length !== 0 ) { out.push(pathin); } - if ( recursive !== true ) { return; } - } - for ( const { obj, key, path } of this.#getDescendants(owner, recursive) ) { - if ( Array.isArray(obj[key]) ) { continue; } - const q = [ ...pathin, ...path ]; + const v2 = this.#compiled.v2 || recursive || Array.isArray(owner); + for ( const { path } of this.#getDescendants(owner, recursive) ) { + const q = v2 ? [ ...pathin, ...path ] : pathin; const r = this.#evaluate(step.steps, q); - if ( r.length === 0 ) { continue; } + if ( Boolean(r?.length) === false ) { continue; } out.push(q); + if ( v2 === false ) { break; } } } - #normalizeKey(owner, key) { - if ( typeof key === 'number' ) { - if ( Array.isArray(owner) ) { - return key >= 0 ? key : owner.length + key; - } - } - return key; - } #getDescendants(v, recursive) { const iterator = { next() { @@ -349,7 +417,7 @@ export class JSONPath { if ( Array.isArray(v) ) { this.stack.push({ obj: v, keys: v.keys() }); } else if ( typeof v === 'object' && v !== null ) { - this.stack.push({ obj: v, keys: Object.keys(v).values() }); + this.stack.push({ obj: v, keys: JSONPath.keys(v).values() }); } } return this; @@ -363,24 +431,32 @@ export class JSONPath { if ( Array.isArray(v) ) { iterator.stack.push({ obj: v, keys: v.keys() }); } else if ( typeof v === 'object' && v !== null ) { - iterator.stack.push({ obj: v, keys: Object.keys(v).values() }); + iterator.stack.push({ obj: v, keys: JSONPath.keys(v).values() }); } return iterator; } #consumeIdentifier(query, i) { const keys = []; - for (;;) { + let needIdentifier = true; + while ( i < query.length ) { const c0 = query.charCodeAt(i); if ( c0 === 0x5D /* ] */ ) { break; } + if ( c0 === 0x20 /* SPACE */ ) { + i += 1; + continue; + } if ( c0 === 0x2C /* , */ ) { + if ( needIdentifier ) { return; } i += 1; + needIdentifier = true; continue; } - if ( c0 === 0x27 /* ' */ ) { - const r = this.#untilChar(query, 0x27 /* ' */, i+1) + if ( c0 === 0x22 /* " */ || c0 === 0x27 /* ' */ ) { + const r = this.#untilChar(query, c0, i+1); if ( r === undefined ) { return; } keys.push(r.s); i = r.i; + needIdentifier = false; continue; } if ( c0 === 0x2D /* - */ || c0 >= 0x30 && c0 <= 0x39 ) { @@ -389,19 +465,29 @@ export class JSONPath { const indice = parseInt(query.slice(i), 10); keys.push(indice); i += match[0].length; + needIdentifier = false; continue; } - const s = this.#consumeUnquotedIdentifier(query, i); - if ( s === undefined ) { return; } - keys.push(s); - i += s.length; + if ( this.v2 ) { return; } + const r = this.#consumeUnquotedIdentifier(query, i); + if ( r === undefined ) { return; } + keys.push(r.s); + i = r.i; } + if ( needIdentifier ) { return; } return { s: keys.length === 1 ? keys[0] : keys, i }; } #consumeUnquotedIdentifier(query, i) { + if ( query.charCodeAt(i) === 0x2F /* / */ ) { + const r = this.#untilChar(query, 0x2F, i+1); + if ( r === undefined ) { return; } + let re; + try { re = new JSONPath.Regex(r.s); } catch { return; } + return { s: re, i: r.i }; + } const match = this.#reUnquotedIdentifier.exec(query.slice(i)); if ( match === null ) { return; } - return match[0]; + return { s: match[0], i: i + match[0].length }; } #untilChar(query, targetCharCode, i) { const len = query.length; @@ -433,22 +519,27 @@ export class JSONPath { if ( r === undefined ) { return i; } const match = /^[i]/.exec(query.slice(r.i)); try { - step.rval = new RegExp(r.s, match && match[0] || undefined); - } catch { - return i; - } + step.rval = new JSONPath.Regex(r.s, match && match[0] || undefined); + } catch { return; } step.op = 're'; if ( match ) { r.i += match[0].length; } return r.i; } const match = this.#reExpr.exec(query.slice(i)); - if ( match === null ) { return i; } - try { - step.rval = JSON.parse(match[2]); - step.op = match[1]; - } catch { + if ( match === null ) { return; } + const op = match[1], rval = match[2]; + if ( rval.charCodeAt(0) === 0x27 /* ' */ ) { + const r = this.#untilChar(rval, 0x27, 1); + if ( r === undefined ) { return; } + step.rval = r.s; + step.op = op; + } else { + try { + step.rval = JSON.parse(rval); + step.op = op; + } catch { return; } } - return i + match[1].length + match[2].length; + return i + match[0].length - 1; } #resolvePath(path) { if ( path.length === 0 ) { return { value: this.#root }; } @@ -456,34 +547,30 @@ export class JSONPath { let obj = this.#root for ( let i = 0, n = path.length-1; i < n; i++ ) { obj = obj[path[i]]; + if ( obj instanceof Object === false ) { return {}; } } return { obj, key, value: obj[key] }; } - #evaluateExpr(step, owner, key) { + #evaluateExpr(step, owner, k) { if ( owner === undefined || owner === null ) { return; } - if ( typeof key === 'number' ) { - if ( Array.isArray(owner) === false ) { return; } - } - const k = this.#normalizeKey(owner, key); - const hasOwn = Object.hasOwn(owner, k); + const hasOwn = owner[k] !== undefined || JSONPath.hasOwn(owner, k); if ( step.op !== undefined && hasOwn === false ) { return; } const target = step.not !== true; const v = owner[k]; - let outcome = false; switch ( step.op ) { - case '==': outcome = (v === step.rval) === target; break; - case '!=': outcome = (v !== step.rval) === target; break; - case '<': outcome = (v < step.rval) === target; break; - case '<=': outcome = (v <= step.rval) === target; break; - case '>': outcome = (v > step.rval) === target; break; - case '>=': outcome = (v >= step.rval) === target; break; - case '^=': outcome = `${v}`.startsWith(step.rval) === target; break; - case '$=': outcome = `${v}`.endsWith(step.rval) === target; break; - case '*=': outcome = `${v}`.includes(step.rval) === target; break; - case 're': outcome = step.rval.test(`${v}`); break; - default: outcome = hasOwn === target; break; + case '==': return (v === step.rval) === target; + case '!=': return (v !== step.rval) === target; + case '<': return (v < step.rval) === target; + case '<=': return (v <= step.rval) === target; + case '>': return (v > step.rval) === target; + case '>=': return (v >= step.rval) === target; + case '^=': return `${v}`.startsWith(step.rval) === target; + case '$=': return `${v}`.endsWith(step.rval) === target; + case '*=': return `${v}`.includes(step.rval) === target; + case 're': return step.rval.test(`${v}`); + default: break; } - if ( outcome ) { return k; } + return hasOwn === target; } #modifyVal(obj, key) { let { modify, rval } = this.#compiled; @@ -499,11 +586,23 @@ export class JSONPath { const lval = obj[key]; if ( lval instanceof Object === false ) { return; } if ( Array.isArray(lval) ) { return; } - for ( const [ k, v ] of Object.entries(rval) ) { + for ( const [ k, v ] of JSONPath.entries(rval) ) { lval[k] = v; } break; } + case 'call': { + const entries = rval.slice(); + if ( entries.length < 2 ) { break; } + entries.forEach((a, i, aa) => { + if ( a === '${obj}' ) { aa[i] = obj; } + else if ( a === '${key}' ) { aa[i] = key; } + else if ( a === '${val}' ) { aa[i] = obj[key]; } + }); + const instance = entries[0] ?? self; + instance[entries[1]](...entries.slice(2)); + break; + } case 'repl': { const lval = obj[key]; if ( typeof lval !== 'string' ) { return; } @@ -511,10 +610,9 @@ export class JSONPath { this.#compiled.re = null; try { this.#compiled.re = rval.regex !== undefined - ? new RegExp(rval.regex, rval.flags) - : new RegExp(rval.pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')); - } catch { - } + ? new JSONPath.Regex(rval.regex, rval.flags) + : new JSONPath.Regex(rval.pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')); + } catch { } } if ( this.#compiled.re === null ) { return; } obj[key] = lval.replace(this.#compiled.re, rval.replacement); diff --git a/src/js/messaging.js b/src/js/messaging.js index 7735d77ba0a88..e76bd7ac42b03 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -42,6 +42,7 @@ import cacheStorage from './cachestorage.js'; import cosmeticFilteringEngine from './cosmetic-filtering.js'; import { denseBase64 } from './base64-custom.js'; import { filteringBehaviorChanged } from './broadcast.js'; +import { getTrustedTokens } from './trusted-tokens.js'; import htmlFilteringEngine from './html-filtering.js'; import { i18n$ } from './i18n.js'; import io from './assets.js'; @@ -155,7 +156,7 @@ const onMessage = function(request, sender, callback) { case 'getAppData': response = { - name: browser.runtime.getManifest().name, + name: self.browser.runtime.getManifest().name, version: vAPI.app.version, canBenchmark: µb.hiddenSettings.benchmarkDatasetURL !== 'unset', }; @@ -165,8 +166,8 @@ const onMessage = function(request, sender, callback) { response = getDomainNames(request.targets); break; - case 'getTrustedScriptletTokens': - response = redirectEngine.getTrustedScriptletTokens(); + case 'getTrustedTokens': + response = Array.from(getTrustedTokens()); break; case 'getWhitelist': diff --git a/src/js/redirect-engine.js b/src/js/redirect-engine.js index 518dcd3c73a2d..2c56ce48fe931 100644 --- a/src/js/redirect-engine.js +++ b/src/js/redirect-engine.js @@ -215,6 +215,7 @@ class RedirectEngine { js: entry.toContent(), world: entry.world, dependencies: entry.dependencies.slice(), + priority: entry.priority ?? 0, }; } @@ -405,7 +406,7 @@ class RedirectEngine { for ( const [ name, entry ] of this.resources ) { out.set(name, { canInject: typeof entry.data === 'string', - canRedirect: entry.warURL !== undefined, + canRedirect: Boolean(entry.warURL ?? entry.data), aliasOf: '', extensionPath: entry.warURL, }); @@ -422,26 +423,6 @@ class RedirectEngine { }); } - getTrustedScriptletTokens() { - const out = []; - const isTrustedScriptlet = entry => { - if ( entry.requiresTrust !== true ) { return false; } - if ( entry.warURL !== undefined ) { return false; } - if ( typeof entry.data !== 'string' ) { return false; } - if ( entry.name.endsWith('.js') === false ) { return false; } - return true; - }; - for ( const [ name, entry ] of this.resources ) { - if ( isTrustedScriptlet(entry) === false ) { continue; } - out.push(name.slice(0, -3)); - } - for ( const [ alias, name ] of this.aliases ) { - if ( out.includes(name.slice(0, -3)) === false ) { continue; } - out.push(alias.slice(0, -3)); - } - return out; - } - selfieFromResources(storage) { return storage.toCache(RESOURCES_SELFIE_NAME, { version: RESOURCES_SELFIE_VERSION, diff --git a/src/js/redirect-resources.js b/src/js/redirect-resources.js index f94383390b59d..313d50ba6a0f0 100644 --- a/src/js/redirect-resources.js +++ b/src/js/redirect-resources.js @@ -99,6 +99,11 @@ export default new Map([ alias: 'google-ima3', /* adguard compatibility */ data: 'text', } ], + [ 'google-ima-dai.js', { + alias: 'google-ima3-dai', /* adguard compatibility */ + data: 'text', + requiresTrust: true, + } ], [ 'googlesyndication_adsbygoogle.js', { alias: [ 'googlesyndication.com/adsbygoogle.js', @@ -118,10 +123,6 @@ export default new Map([ [ 'nitropay_ads.js', { data: 'text', } ], - [ 'nobab.js', { - alias: [ 'bab-defuser.js', 'prevent-bab.js' ], - data: 'text', - } ], [ 'nobab2.js', { data: 'text', } ], @@ -183,6 +184,8 @@ export default new Map([ [ 'outbrain-widget.js', { alias: 'widgets.outbrain.com/outbrain.js', } ], + [ 'piano-analytics.js', { + } ], [ 'popads.js', { alias: [ 'popads.net.js', 'prevent-popads-net.js' ], data: 'text', diff --git a/src/js/regex-analyzer.js b/src/js/regex-analyzer.js index a46ac60277b78..9d241703fc0c1 100644 --- a/src/js/regex-analyzer.js +++ b/src/js/regex-analyzer.js @@ -19,13 +19,11 @@ Home: https://github.com/gorhill/uBlock */ -import Regex from '../lib/regexanalyzer/regex.js'; - /******************************************************************************/ // Depends on: // https://github.com/foo123/RegexAnalyzer -const RegexAnalyzer = Regex && Regex.Analyzer || null; +const RegexAnalyzer = globalThis.Regex && globalThis.Regex.Analyzer || null; export function isRE2(reStr) { if ( RegexAnalyzer === null ) { return true; } diff --git a/src/js/resources/abort-current-script.js b/src/js/resources/abort-current-script.js new file mode 100644 index 0000000000000..c25ba07219968 --- /dev/null +++ b/src/js/resources/abort-current-script.js @@ -0,0 +1,123 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2019-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock + +*/ + +import { getExceptionTokenFn, trapPropertyFn } from './utils.js'; +import { registerScriptlet } from './base.js'; +import { runAtHtmlElementFn } from './run-at.js'; +import { safeSelf } from './safe-self.js'; + +/******************************************************************************/ + +// Issues to mind before changing anything: +// https://github.com/uBlockOrigin/uBlock-issues/issues/2154 +function abortCurrentScriptFn( + target = '', + needle = '', + context = '' +) { + if ( typeof target !== 'string' ) { return; } + if ( target === '' ) { return; } + const safe = safeSelf(); + const logPrefix = safe.makeLogPrefix('abort-current-script', target, needle, context); + const reNeedle = safe.patternToRegex(needle); + const reContext = safe.patternToRegex(context); + const thisScript = document.currentScript; + const exceptionToken = getExceptionTokenFn(); + const scriptTexts = new WeakMap(); + const textContentGetter = Object.getOwnPropertyDescriptor(Node.prototype, 'textContent').get; + const getScriptText = elem => { + let text = textContentGetter.call(elem); + if ( text.trim() !== '' ) { return text; } + if ( scriptTexts.has(elem) ) { return scriptTexts.get(elem); } + const [ , mime, content ] = /^data:([^,]*),(.+)$/.exec(elem.src.trim()) || + [ '', '', '' ]; + try { + switch ( true ) { + case mime.endsWith(';base64'): + text = self.atob(content); + break; + default: + text = self.decodeURIComponent(content); + break; + } + } catch { + } + scriptTexts.set(elem, text); + return text; + }; + const validate = ( ) => { + const e = document.currentScript; + if ( e instanceof HTMLScriptElement === false ) { return; } + if ( e === thisScript ) { return; } + if ( context !== '' && reContext.test(e.src) === false ) { return; } + if ( safe.logLevel > 1 && context !== '' ) { + safe.uboLog(logPrefix, `Matched src\n${e.src}`); + } + const scriptText = getScriptText(e); + if ( reNeedle.test(scriptText) === false ) { return; } + if ( safe.logLevel > 1 ) { + safe.uboLog(logPrefix, `Matched text\n${scriptText}`); + } + safe.uboLog(logPrefix, 'Aborted'); + throw new ReferenceError(exceptionToken); + }; + let currentValue = trapPropertyFn(target, { + get: function() { + validate(); + return currentValue; + }, + set: function(a) { + validate(); + currentValue = a; + } + }, { canThrow: true }); +} +registerScriptlet(abortCurrentScriptFn , { + name: 'abort-current-script.fn', + dependencies: [ + getExceptionTokenFn, + safeSelf, + trapPropertyFn, + ], +}); + +/******************************************************************************/ + +// Issues to mind before changing anything: +// https://github.com/uBlockOrigin/uBlock-issues/issues/2154 +export function abortCurrentScript(...args) { + runAtHtmlElementFn(( ) => { + abortCurrentScriptFn(...args); + }); +} +registerScriptlet(abortCurrentScript , { + name: 'abort-current-script.js', + aliases: [ + 'abort-current-inline-script.js', + 'acis.js', + 'acs.js', + ], + dependencies: [ + abortCurrentScriptFn, + runAtHtmlElementFn, + ], +}); diff --git a/src/js/resources/attribute.js b/src/js/resources/attribute.js index 6063097620be3..82fb4bd990620 100644 --- a/src/js/resources/attribute.js +++ b/src/js/resources/attribute.js @@ -20,6 +20,7 @@ */ +import { offIdleFn, onIdleFn } from './utils.js'; import { registerScriptlet } from './base.js'; import { runAt } from './run-at.js'; import { safeSelf } from './safe-self.js'; @@ -89,10 +90,9 @@ export function setAttrFn( const start = ( ) => { if ( applySetAttr() === false ) { return; } observer = new MutationObserver(onDomChanged); - observer.observe(document.body, { - subtree: true, - childList: true, - }); + const root = document.documentElement; + if ( root instanceof self.Node === false ) { return; } + observer.observe(root, { subtree: true, childList: true }); }; runAt(( ) => { start(); }, options.runAt || 'idle'); } @@ -132,7 +132,8 @@ registerScriptlet(setAttrFn, { export function setAttr( selector = '', attr = '', - value = '' + value = '', + ...varargs ) { const safe = safeSelf(); const logPrefix = safe.makeLogPrefix('set-attr', selector, attr, value); @@ -146,7 +147,7 @@ export function setAttr( return; } } - const options = safe.getExtraArgs(Array.from(arguments), 3); + const options = safe.parseVarargs(varargs); setAttrFn(false, logPrefix, selector, attr, value, options); } registerScriptlet(setAttr, { @@ -182,11 +183,12 @@ registerScriptlet(setAttr, { export function trustedSetAttr( selector = '', attr = '', - value = '' + value = '', + ...varargs ) { const safe = safeSelf(); const logPrefix = safe.makeLogPrefix('trusted-set-attr', selector, attr, value); - const options = safe.getExtraArgs(Array.from(arguments), 3); + const options = safe.parseVarargs(varargs); setAttrFn(true, logPrefix, selector, attr, value, options); } registerScriptlet(trustedSetAttr, { @@ -216,72 +218,81 @@ registerScriptlet(trustedSetAttr, { * * @param [behavior] * Optional. Space-separated tokens which modify the default behavior. - * - `asap`: Try to remove the attribute as soon as possible. Default behavior - * is to remove the attribute(s) asynchronously. * - `stay`: Keep trying to remove the specified attribute(s) on DOM mutations. + * + * @params [...varargs] + * Optional, any of following pairs of parameters: + * - `quitAfter, sec`: where `sec` is the number of seconds after which the + * scriptlet ceases to be active. This has precedence over `stay` behavior. * */ export function removeAttr( rawToken = '', rawSelector = '', - behavior = '' + behavior = '', + ...varargs ) { if ( typeof rawToken !== 'string' ) { return; } if ( rawToken === '' ) { return; } const safe = safeSelf(); - const logPrefix = safe.makeLogPrefix('remove-attr', rawToken, rawSelector, behavior); + const logPrefix = safe.makeLogPrefix('remove-attr', + rawToken, rawSelector, behavior, ...varargs + ); const tokens = safe.String_split.call(rawToken, /\s*\|\s*/); - const selector = tokens - .map(a => `${rawSelector}[${CSS.escape(a)}]`) - .join(','); + const selector = tokens.map(a => { + const b = CSS.escape(a); + return rawSelector.includes(`[${b}]`) ? rawSelector : `${rawSelector}[${b}]`; + }).join(','); + const lazily = /\basap\b/.test(behavior) === false; + const options = safe.parseVarargs(varargs); if ( safe.logLevel > 1 ) { safe.uboLog(logPrefix, `Target selector:\n\t${selector}`); } - const asap = /\basap\b/.test(behavior); - let timerId; - const rmattrAsync = ( ) => { - if ( timerId !== undefined ) { return; } - timerId = safe.onIdle(( ) => { - timerId = undefined; - rmattr(); - }, { timeout: 17 }); - }; - const rmattr = ( ) => { - if ( timerId !== undefined ) { - safe.offIdle(timerId); - timerId = undefined; + const rmattrFromNode = node => { + for ( const attr of tokens ) { + if ( node.hasAttribute(attr) === false ) { continue; } + node.removeAttribute(attr); + safe.uboLog(logPrefix, `Removed attribute '${attr}'`); } - try { - const nodes = document.querySelectorAll(selector); - for ( const node of nodes ) { - for ( const attr of tokens ) { - if ( node.hasAttribute(attr) === false ) { continue; } - node.removeAttribute(attr); - safe.uboLog(logPrefix, `Removed attribute '${attr}'`); - } - } - } catch { + }; + const rmattr = nodes => { + for ( const node of nodes ?? document.querySelectorAll(selector) ) { + rmattrFromNode(node); } }; + const rmAttrLazily = ( ) => { + if ( rmAttrLazily.timer !== undefined ) { return; } + rmAttrLazily.timer = onIdleFn(( ) => { + rmAttrLazily.timer = undefined; + rmattr(); + }, { timeout: 17 }); + }; const mutationHandler = mutations => { - if ( timerId !== undefined ) { return; } - let skip = true; - for ( let i = 0; i < mutations.length && skip; i++ ) { - const { type, addedNodes, removedNodes } = mutations[i]; - if ( type === 'attributes' ) { skip = false; } - for ( let j = 0; j < addedNodes.length && skip; j++ ) { - if ( addedNodes[j].nodeType === 1 ) { skip = false; break; } + for ( const { addedNodes, removedNodes } of mutations ) { + for ( const node of addedNodes ) { + if ( node.nodeType !== 1 ) { continue; } + if ( lazily ) { return rmAttrLazily(); } + if ( node.matches(selector) ) { + rmattrFromNode(node); + } + if ( node.childElementCount ) { + rmattr(node.querySelectorAll(selector)); + } } - for ( let j = 0; j < removedNodes.length && skip; j++ ) { - if ( removedNodes[j].nodeType === 1 ) { skip = false; break; } + if ( lazily ) { return; } + for ( const node of removedNodes ) { + if ( node.nodeType !== 1 ) { continue; } + if ( node.matches(selector) ) { + rmattrFromNode(node); + } } } - if ( skip ) { return; } - asap ? rmattr() : rmattrAsync(); }; const start = ( ) => { rmattr(); - if ( /\bstay\b/.test(behavior) === false ) { return; } + if ( /\bstay\b/.test(behavior) === false ) { + if ( options.quitAfter === undefined ) { return; } + } const observer = new MutationObserver(mutationHandler); observer.observe(document, { attributes: true, @@ -289,6 +300,18 @@ export function removeAttr( childList: true, subtree: true, }); + if ( options.quitAfter ) { + self.setTimeout(( ) => { + observer.disconnect(); + if ( rmAttrLazily.timer ) { + offIdleFn(rmAttrLazily.timer); + rmAttrLazily.timer = undefined; + } + if ( safe.logLevel > 1 ) { + safe.uboLog(logPrefix, 'Quitting'); + } + }, options.quitAfter * 1000); + } }; runAt(( ) => { start(); }, safe.String_split.call(behavior, /\s+/)); } @@ -298,6 +321,8 @@ registerScriptlet(removeAttr, { 'ra.js', ], dependencies: [ + offIdleFn, + onIdleFn, runAt, safeSelf, ], diff --git a/src/js/resources/cookie.js b/src/js/resources/cookie.js index 21300bc650041..79cda65b6d82f 100644 --- a/src/js/resources/cookie.js +++ b/src/js/resources/cookie.js @@ -49,6 +49,8 @@ export function getSafeCookieValuesFn() { 'decline', 'declined', 'closed', 'next', 'mandatory', 'disagree', 'agree', + 'set', 'unset', + 'given', ]; } registerScriptlet(getSafeCookieValuesFn, { @@ -193,7 +195,8 @@ registerScriptlet(setCookieFn, { export function setCookie( name = '', value = '', - path = '' + path = '', + ...varargs ) { if ( name === '' ) { return; } const safe = safeSelf(); @@ -214,7 +217,7 @@ export function setCookie( value, '', path, - safe.getExtraArgs(Array.from(arguments), 3) + safe.parseVarargs(varargs) ); if ( done ) { @@ -271,7 +274,8 @@ export function trustedSetCookie( name = '', value = '', offsetExpiresSec = '', - path = '' + path = '', + ...varargs ) { if ( name === '' ) { return; } @@ -308,7 +312,7 @@ export function trustedSetCookie( value, expires, path, - safeSelf().getExtraArgs(Array.from(arguments), 4) + safe.parseVarargs(varargs) ); if ( done ) { @@ -357,12 +361,13 @@ registerScriptlet(trustedSetCookieReload, { * */ export function removeCookie( - needle = '' + needle = '', + ...varargs ) { if ( typeof needle !== 'string' ) { return; } const safe = safeSelf(); const reName = safe.patternToRegex(needle); - const extraArgs = safe.getExtraArgs(Array.from(arguments), 1); + const extraArgs = safe.parseVarargs(varargs); const throttle = (fn, ms = 500) => { if ( throttle.timer !== undefined ) { return; } throttle.timer = setTimeout(( ) => { diff --git a/src/js/resources/create-html.js b/src/js/resources/create-html.js index 33b5a99f37541..468083d36034e 100644 --- a/src/js/resources/create-html.js +++ b/src/js/resources/create-html.js @@ -50,13 +50,14 @@ import { safeSelf } from './safe-self.js'; function trustedCreateHTML( parentSelector, htmlStr = '', - durationStr = '' + durationStr = '', + ...varargs ) { if ( parentSelector === '' ) { return; } if ( htmlStr === '' ) { return; } const safe = safeSelf(); const logPrefix = safe.makeLogPrefix('trusted-create-html', parentSelector, htmlStr, durationStr); - const extraArgs = safe.getExtraArgs(Array.from(arguments), 3); + const extraArgs = safe.parseVarargs(varargs); // We do not want to recursively create elements self.trustedCreateHTML = true; let ancestor = self.frameElement; diff --git a/src/js/resources/href-sanitizer.js b/src/js/resources/href-sanitizer.js index 8b35d3fbfdd5a..3be7066f69c16 100644 --- a/src/js/resources/href-sanitizer.js +++ b/src/js/resources/href-sanitizer.js @@ -20,6 +20,7 @@ */ +import { onIdleFn } from './utils.js'; import { registerScriptlet } from './base.js'; import { runAt } from './run-at.js'; import { safeSelf } from './safe-self.js'; @@ -141,7 +142,7 @@ function hrefSanitizer( if ( shouldSanitize ) { break; } } if ( shouldSanitize === false ) { return; } - timer = safe.onIdle(( ) => { + timer = onIdleFn(( ) => { timer = undefined; sanitize(); }); @@ -163,6 +164,7 @@ registerScriptlet(hrefSanitizer, { 'urlskip.js', ], dependencies: [ + onIdleFn, runAt, safeSelf, urlSkip, diff --git a/src/js/resources/json-edit.js b/src/js/resources/json-edit.js index e4c6a83821077..d50d4a2820647 100644 --- a/src/js/resources/json-edit.js +++ b/src/js/resources/json-edit.js @@ -22,8 +22,11 @@ import { collateFetchArgumentsFn, + lookupElementsFn, matchObjectPropertiesFn, parsePropertiesToMatchFn, + sleepFn, + trapPropertyFn, } from './utils.js'; import { JSONPath } from './shared.js'; @@ -37,7 +40,7 @@ import { safeSelf } from './safe-self.js'; function editOutboundObjectFn( trusted = false, propChain = '', - jsonq = '', + jsonq = '' ) { if ( propChain === '' ) { return; } const safe = safeSelf(); @@ -124,6 +127,42 @@ registerScriptlet(trustedEditOutboundObject, { }); /******************************************************************************/ + +function jsonEditFn(trusted = false, jsonq = '', ...varargs) { + const safe = safeSelf(); + const logPrefix = safe.makeLogPrefix( + `${trusted ? 'trusted-' : ''}json-edit`, + jsonq, + ...varargs + ); + const jsonp = JSONPath.create(jsonq); + if ( jsonp.valid === false || jsonp.value !== undefined && trusted !== true ) { + return safe.uboLog(logPrefix, 'Bad JSONPath query'); + } + const extraArgs = safe.parseVarargs(varargs); + const pattern = extraArgs.matches && safe.initPattern(extraArgs.matches); + proxyApplyFn('JSON.parse', function(context) { + const json = context.callArgs[0]; + const obj = context.reflect(); + if ( pattern && safe.testPattern(pattern, json) === false ) { return obj; } + const objAfter = jsonp.apply(obj); + if ( objAfter === undefined ) { return obj; } + safe.uboLog(logPrefix, 'Edited'); + if ( safe.logLevel > 1 ) { + safe.uboLog(logPrefix, `After edit:\n${safe.JSON_stringify(objAfter, null, 2)}`); + } + return objAfter; + }); +} +registerScriptlet(jsonEditFn, { + name: 'json-edit.fn', + dependencies: [ + JSONPath, + proxyApplyFn, + safeSelf, + ], +}); + /******************************************************************************/ /** * @scriptlet json-edit.js @@ -135,15 +174,20 @@ registerScriptlet(trustedEditOutboundObject, { * @param jsonq * A uBO-flavored JSONPath query. * + * @param 'matches', pattern + * Vararg, optional: The JSONPath will be applied if and only if the pattern + * matches the inbound JSON string. The pattern can be a plain string or a + * regex. + * * */ -function jsonEdit(jsonq = '') { - editOutboundObjectFn(false, 'JSON.parse', jsonq); +function jsonEdit(jsonq = '', ...varargs) { + jsonEditFn(false, jsonq, ...varargs); } registerScriptlet(jsonEdit, { name: 'json-edit.js', dependencies: [ - editOutboundObjectFn, + jsonEditFn, ], }); @@ -158,16 +202,21 @@ registerScriptlet(jsonEdit, { * @param jsonq * A uBO-flavored JSONPath query. * + * @param 'matches', pattern + * Vararg, optional: The JSONPath will be applied if and only if the pattern + * matches the inbound JSON string. The pattern can be a plain string or a + * regex. + * * */ -function trustedJsonEdit(jsonq = '') { - editOutboundObjectFn(true, 'JSON.parse', jsonq); +function trustedJsonEdit(jsonq = '', ...varargs) { + jsonEditFn(true, jsonq, ...varargs); } registerScriptlet(trustedJsonEdit, { name: 'trusted-json-edit.js', requiresTrust: true, dependencies: [ - editOutboundObjectFn, + jsonEditFn, ], }); @@ -301,7 +350,435 @@ registerScriptlet(trustedEditInboundObject, { /******************************************************************************/ /******************************************************************************/ -function jsonEditXhrResponseFn(trusted, jsonq = '') { +function editThisObjectFn( + trusted = false, + propChain = '', + jsonq = '', + order = '' +) { + if ( propChain === '' ) { return; } + const safe = safeSelf(); + const logPrefix = safe.makeLogPrefix( + `${trusted ? 'trusted-' : ''}edit-this-object`, + propChain, + jsonq + ); + const jsonp = JSONPath.create(jsonq); + if ( jsonp.valid === false || jsonp.value !== undefined && trusted !== true ) { + return safe.uboLog(logPrefix, 'Bad JSONPath query'); + } + const editObj = objBefore => { + const objAfter = jsonp.apply(objBefore); + if ( objAfter === undefined ) { return; } + safe.uboLog(logPrefix, 'Edited'); + if ( safe.logLevel <= 1 ) { return; } + safe.uboLog(logPrefix, `After edit:\n${safe.JSON_stringify(objAfter, null, 2)}`); + }; + proxyApplyFn(propChain, function(context) { + const { thisArg } = context; + let r; + if ( order === 'after' ) { + r = context.reflect(); + } + editObj(thisArg); + if ( order !== 'after' ) { + r = context.reflect(); + } + return r; + }); +} +registerScriptlet(editThisObjectFn, { + name: 'edit-this-object.fn', + dependencies: [ + JSONPath, + proxyApplyFn, + safeSelf, + ], +}); + +/******************************************************************************/ +/** + * @scriptlet edit-this-object.js + * + * @description + * Prune properties from an object through one of the object's own method. + * Properties can only be removed. + * + * @param propChain + * Property chain of the method to trap. + * + * @param jsonq + * A uBO-flavored JSONPath query. + * + * @param order + * If set to `after`, the `this` object will be edited after the trapped method + * is called. By default the `this` object is edited before calling the trapped + * method. + * + * */ + +function editThisObject(...args) { + editThisObjectFn(false, ...args); +} +registerScriptlet(editThisObject, { + name: 'edit-this-object.js', + dependencies: [ + editThisObjectFn, + ], +}); + +/******************************************************************************/ +/** + * @scriptlet trusted-edit-this-object.js + * + * @description + * Edit properties of an object through one of the object's own method. + * Properties can be assigned new values. + * + * @param propChain + * Property chain of the method to trap. + * + * @param jsonq + * A uBO-flavored JSONPath query. + * + * @param order + * If set to `after`, the `this` object will be edited after the trapped method + * is called. By default the `this` object is edited before calling the trapped + * method. + * + * */ + +function trustedEditThisObject(...args) { + editThisObjectFn(true, ...args); +} +registerScriptlet(trustedEditThisObject, { + name: 'trusted-edit-this-object.js', + requiresTrust: true, + dependencies: [ + editThisObjectFn, + ], +}); + +/******************************************************************************/ +/******************************************************************************/ + +function editObjectOnGetterFn( + trusted = false, + propChain = '', + jsonq = '', +) { + if ( propChain === '' ) { return; } + const safe = safeSelf(); + const logPrefix = safe.makeLogPrefix( + `${trusted ? 'trusted-' : ''}edit-object-on-getter`, + propChain, + jsonq + ); + const jsonp = JSONPath.create(jsonq); + if ( jsonp.valid === false || jsonp.value !== undefined && trusted !== true ) { + return safe.uboLog(logPrefix, 'Bad JSONPath query'); + } + const editObj = objBefore => { + const objAfter = jsonp.apply(objBefore); + if ( objAfter === undefined ) { return; } + safe.uboLog(logPrefix, 'Edited'); + if ( safe.logLevel <= 1 ) { return; } + safe.uboLog(logPrefix, `After edit:\n${safe.JSON_stringify(objAfter, null, 2)}`); + }; + let currentValue = trapPropertyFn(propChain, { + get: function() { + if ( currentValue instanceof Object ) { + editObj(currentValue); + } + return currentValue; + }, + set: function(a) { + currentValue = a; + } + }); +} +registerScriptlet(editObjectOnGetterFn, { + name: 'edit-object-on-getter.fn', + dependencies: [ + JSONPath, + safeSelf, + trapPropertyFn, + ], +}); + +/******************************************************************************/ +/** + * @scriptlet edit-object-on-getter.js + * + * @description + * Prune properties from an object on read access. + * Properties can only be removed. + * + * @param propChain + * Property chain of the property to trap. + * + * @param jsonq + * A uBO-flavored JSONPath query. + * + * */ + +function editObjectOnGetter(...args) { + editObjectOnGetterFn(false, ...args); +} +registerScriptlet(editObjectOnGetter, { + name: 'edit-object-on-getter.js', + dependencies: [ + editObjectOnGetterFn, + ], +}); + +/******************************************************************************/ +/** + * @scriptlet trusted-edit-object-on-getter.js + * + * @description + * Edit properties of an object on read access. + * Properties can be assigned new values. + * + * @param propChain + * Property chain of the property to trap. + * + * @param jsonq + * A uBO-flavored JSONPath query. + * + * */ + +function trustedEditObjectOnGetter(...args) { + editObjectOnGetterFn(true, ...args); +} +registerScriptlet(trustedEditObjectOnGetter, { + name: 'trusted-edit-object-on-getter.js', + requiresTrust: true, + dependencies: [ + editObjectOnGetterFn, + ], +}); + +/******************************************************************************/ +/******************************************************************************/ + +function editObjectOnSetterFn( + trusted = false, + propChain = '', + jsonq = '', +) { + if ( propChain === '' ) { return; } + const safe = safeSelf(); + const logPrefix = safe.makeLogPrefix( + `${trusted ? 'trusted-' : ''}edit-object-on-setter`, + propChain, + jsonq + ); + const jsonp = JSONPath.create(jsonq); + if ( jsonp.valid === false || jsonp.value !== undefined && trusted !== true ) { + return safe.uboLog(logPrefix, 'Bad JSONPath query'); + } + const editObj = objBefore => { + const objAfter = jsonp.apply(objBefore); + if ( objAfter === undefined ) { return; } + safe.uboLog(logPrefix, 'Edited'); + if ( safe.logLevel <= 1 ) { return; } + safe.uboLog(logPrefix, `After edit:\n${safe.JSON_stringify(objAfter, null, 2)}`); + }; + let currentValue = trapPropertyFn(propChain, { + get: function() { + return currentValue; + }, + set: function(a) { + currentValue = a; + if ( currentValue instanceof Object ) { + editObj(currentValue); + } + } + }); + if ( currentValue instanceof Object ) { + editObj(currentValue); + } +} +registerScriptlet(editObjectOnSetterFn, { + name: 'edit-object-on-setter.fn', + dependencies: [ + JSONPath, + safeSelf, + trapPropertyFn, + ], +}); + +/******************************************************************************/ +/** + * @scriptlet edit-object-on-setter.js + * + * @description + * Prune properties from an object on write access. + * Properties can only be removed. + * + * @param propChain + * Property chain of the property to trap. + * + * @param jsonq + * A uBO-flavored JSONPath query. + * + * */ + +function editObjectOnSetter(...args) { + editObjectOnSetterFn(false, ...args); +} +registerScriptlet(editObjectOnSetter, { + name: 'edit-object-on-setter.js', + dependencies: [ + editObjectOnSetterFn, + ], +}); + +/******************************************************************************/ +/** + * @scriptlet trusted-edit-object-on-setter.js + * + * @description + * Edit properties of an object on write access. + * Properties can be assigned new values. + * + * @param propChain + * Property chain of the property to trap. + * + * @param jsonq + * A uBO-flavored JSONPath query. + * + * */ + +function trustedEditObjectOnSetter(...args) { + editObjectOnSetterFn(true, ...args); +} +registerScriptlet(trustedEditObjectOnSetter, { + name: 'trusted-edit-object-on-setter.js', + requiresTrust: true, + dependencies: [ + editObjectOnSetterFn, + ], +}); + +/******************************************************************************/ +/******************************************************************************/ + +async function editElementObjectFn( + trusted = false, + selector = '', + jsonq = '', + timeout = '' +) { + if ( selector === '' ) { return; } + const safe = safeSelf(); + const logPrefix = safe.makeLogPrefix( + `${trusted ? 'trusted-' : ''}edit-element-object`, + selector, jsonq, timeout + ); + const jsonp = JSONPath.create(jsonq); + if ( jsonp.valid === false || jsonp.value !== undefined && trusted !== true ) { + return safe.uboLog(logPrefix, 'Bad JSONPath query'); + } + const process = elems => { + for ( const elem of elems ) { + const r = jsonp.apply(elem); + if ( r === undefined ) { continue; } + safe.uboLog(logPrefix, 'Edited'); + } + }; + const until = timeout !== '' ? Date.now() + parseInt(timeout, 10) : 0; + do { + const r = lookupElementsFn(selector, until); + if ( Array.isArray(r) ) { + process(r); + } else if ( r instanceof Promise ) { + const elems = await r; + process(elems); + } + await sleepFn(); + } while ( Date.now() < until ); +} +registerScriptlet(editElementObjectFn, { + name: 'edit-element-object.fn', + dependencies: [ + JSONPath, + lookupElementsFn, + safeSelf, + sleepFn, + ], +}); + +/******************************************************************************/ +/** + * @scriptlet edit-element-object.js + * + * @description + * Prune properties of one or more elements matching a specific selector. + * Properties can only be removed. + * + * @param selector + * The selector used to locate the elements on which the JSONPath query will + * be applied. + * + * @param jsonq + * A uBO-flavored JSONPath query. + * + * @param timeout + * The maximum time (in milliseconds) to wait for matching elements before + * stopping. Defaults to 0, which executes a single lookup attempt without + * waiting. + * + * */ + +function editElementObject(...args) { + editElementObjectFn(false, ...args); +} +registerScriptlet(editElementObject, { + name: 'edit-element-object.js', + dependencies: [ + editElementObjectFn, + ], +}); + +/******************************************************************************/ +/** + * @scriptlet trusted-element-this-object.js + * + * @description + * Edit properties of one or more elements matching a specific selector. + * Properties can be assigned new values. + * + * @param selector + * The selector used to locate the elements on which the JSONPath query will + * be applied. + * + * @param jsonq + * A uBO-flavored JSONPath query. + * + * @param timeout + * The maximum time (in milliseconds) to wait for matching elements before + * stopping. Defaults to 0, which executes a single lookup attempt without + * waiting. + * + * */ + +function trustedEditElementObject(...args) { + editElementObjectFn(true, ...args); +} +registerScriptlet(trustedEditElementObject, { + name: 'trusted-edit-element-object.js', + requiresTrust: true, + dependencies: [ + editElementObjectFn, + ], +}); + +/******************************************************************************/ +/******************************************************************************/ + +function jsonEditXhrResponseFn(trusted, jsonq = '', ...varargs) { const safe = safeSelf(); const logPrefix = safe.makeLogPrefix( `${trusted ? 'trusted-' : ''}json-edit-xhr-response`, @@ -312,7 +789,7 @@ function jsonEditXhrResponseFn(trusted, jsonq = '') { if ( jsonp.valid === false || jsonp.value !== undefined && trusted !== true ) { return safe.uboLog(logPrefix, 'Bad JSONPath query'); } - const extraArgs = safe.getExtraArgs(Array.from(arguments), 2); + const extraArgs = safe.parseVarargs(varargs); const propNeedles = parsePropertiesToMatchFn(extraArgs.propsToMatch, 'url'); self.XMLHttpRequest = class extends self.XMLHttpRequest { open(method, url, ...args) { @@ -436,7 +913,7 @@ registerScriptlet(trustedJsonEditXhrResponse, { /******************************************************************************/ /******************************************************************************/ -function jsonEditXhrRequestFn(trusted, jsonq = '') { +function jsonEditXhrRequestFn(trusted, jsonq = '', ...varargs) { const safe = safeSelf(); const logPrefix = safe.makeLogPrefix( `${trusted ? 'trusted-' : ''}json-edit-xhr-request`, @@ -447,7 +924,7 @@ function jsonEditXhrRequestFn(trusted, jsonq = '') { if ( jsonp.valid === false || jsonp.value !== undefined && trusted !== true ) { return safe.uboLog(logPrefix, 'Bad JSONPath query'); } - const extraArgs = safe.getExtraArgs(Array.from(arguments), 2); + const extraArgs = safe.parseVarargs(varargs); const propNeedles = parsePropertiesToMatchFn(extraArgs.propsToMatch, 'url'); self.XMLHttpRequest = class extends self.XMLHttpRequest { open(method, url, ...args) { @@ -554,7 +1031,7 @@ registerScriptlet(trustedJsonEditXhrRequest, { /******************************************************************************/ /******************************************************************************/ -function jsonEditFetchResponseFn(trusted, jsonq = '') { +function jsonEditFetchResponseFn(trusted, jsonq = '', ...varargs) { const safe = safeSelf(); const logPrefix = safe.makeLogPrefix( `${trusted ? 'trusted-' : ''}json-edit-fetch-response`, @@ -564,7 +1041,7 @@ function jsonEditFetchResponseFn(trusted, jsonq = '') { if ( jsonp.valid === false || jsonp.value !== undefined && trusted !== true ) { return safe.uboLog(logPrefix, 'Bad JSONPath query'); } - const extraArgs = safe.getExtraArgs(Array.from(arguments), 2); + const extraArgs = safe.parseVarargs(varargs); const propNeedles = parsePropertiesToMatchFn(extraArgs.propsToMatch, 'url'); proxyApplyFn('fetch', function(context) { const args = context.callArgs; @@ -676,7 +1153,7 @@ registerScriptlet(trustedJsonEditFetchResponse, { /******************************************************************************/ /******************************************************************************/ -function jsonEditFetchRequestFn(trusted, jsonq = '') { +function jsonEditFetchRequestFn(trusted, jsonq = '', ...varargs) { const safe = safeSelf(); const logPrefix = safe.makeLogPrefix( `${trusted ? 'trusted-' : ''}json-edit-fetch-request`, @@ -686,7 +1163,7 @@ function jsonEditFetchRequestFn(trusted, jsonq = '') { if ( jsonp.valid === false || jsonp.value !== undefined && trusted !== true ) { return safe.uboLog(logPrefix, 'Bad JSONPath query'); } - const extraArgs = safe.getExtraArgs(Array.from(arguments), 2); + const extraArgs = safe.parseVarargs(varargs); const propNeedles = parsePropertiesToMatchFn(extraArgs.propsToMatch, 'url'); const filterBody = body => { if ( typeof body !== 'string' ) { return; } @@ -825,7 +1302,7 @@ registerScriptlet(jsonlEditFn, { /******************************************************************************/ -function jsonlEditXhrResponseFn(trusted, jsonq = '') { +function jsonlEditXhrResponseFn(trusted, jsonq = '', ...varargs) { const safe = safeSelf(); const logPrefix = safe.makeLogPrefix( `${trusted ? 'trusted-' : ''}jsonl-edit-xhr-response`, @@ -836,7 +1313,7 @@ function jsonlEditXhrResponseFn(trusted, jsonq = '') { if ( jsonp.valid === false || jsonp.value !== undefined && trusted !== true ) { return safe.uboLog(logPrefix, 'Bad JSONPath query'); } - const extraArgs = safe.getExtraArgs(Array.from(arguments), 2); + const extraArgs = safe.parseVarargs(varargs); const propNeedles = parsePropertiesToMatchFn(extraArgs.propsToMatch, 'url'); self.XMLHttpRequest = class extends self.XMLHttpRequest { open(method, url, ...args) { @@ -953,7 +1430,7 @@ registerScriptlet(trustedJsonlEditXhrResponse, { /******************************************************************************/ /******************************************************************************/ -function jsonlEditFetchResponseFn(trusted, jsonq = '') { +function jsonlEditFetchResponseFn(trusted, jsonq = '', ...varargs) { const safe = safeSelf(); const logPrefix = safe.makeLogPrefix( `${trusted ? 'trusted-' : ''}jsonl-edit-fetch-response`, @@ -963,7 +1440,7 @@ function jsonlEditFetchResponseFn(trusted, jsonq = '') { if ( jsonp.valid === false || jsonp.value !== undefined && trusted !== true ) { return safe.uboLog(logPrefix, 'Bad JSONPath query'); } - const extraArgs = safe.getExtraArgs(Array.from(arguments), 2); + const extraArgs = safe.parseVarargs(varargs); const propNeedles = parsePropertiesToMatchFn(extraArgs.propsToMatch, 'url'); const logall = jsonq === ''; proxyApplyFn('fetch', function(context) { diff --git a/src/js/resources/json-prune.js b/src/js/resources/json-prune.js index aa787841835ff..22c5dc46f7bf3 100644 --- a/src/js/resources/json-prune.js +++ b/src/js/resources/json-prune.js @@ -36,12 +36,13 @@ import { safeSelf } from './safe-self.js'; function jsonPrune( rawPrunePaths = '', rawNeedlePaths = '', - stackNeedle = '' + stackNeedle = '', + ...varargs ) { const safe = safeSelf(); const logPrefix = safe.makeLogPrefix('json-prune', rawPrunePaths, rawNeedlePaths, stackNeedle); const stackNeedleDetails = safe.initPattern(stackNeedle, { canNegate: true }); - const extraArgs = safe.getExtraArgs(Array.from(arguments), 3); + const extraArgs = safe.parseVarargs(varargs); proxyApplyFn('JSON.parse', function(context) { const objBefore = context.reflect(); if ( rawPrunePaths === '' ) { @@ -75,11 +76,12 @@ registerScriptlet(jsonPrune, { function jsonPruneFetchResponse( rawPrunePaths = '', - rawNeedlePaths = '' + rawNeedlePaths = '', + ...varargs ) { const safe = safeSelf(); const logPrefix = safe.makeLogPrefix('json-prune-fetch-response', rawPrunePaths, rawNeedlePaths); - const extraArgs = safe.getExtraArgs(Array.from(arguments), 2); + const extraArgs = safe.parseVarargs(varargs); const propNeedles = parsePropertiesToMatchFn(extraArgs.propsToMatch, 'url'); const stackNeedle = safe.initPattern(extraArgs.stackToMatch || '', { canNegate: true }); const logall = rawPrunePaths === ''; @@ -150,12 +152,13 @@ registerScriptlet(jsonPruneFetchResponse, { function jsonPruneXhrResponse( rawPrunePaths = '', - rawNeedlePaths = '' + rawNeedlePaths = '', + ...varargs ) { const safe = safeSelf(); const logPrefix = safe.makeLogPrefix('json-prune-xhr-response', rawPrunePaths, rawNeedlePaths); const xhrInstances = new WeakMap(); - const extraArgs = safe.getExtraArgs(Array.from(arguments), 2); + const extraArgs = safe.parseVarargs(varargs); const propNeedles = parsePropertiesToMatchFn(extraArgs.propsToMatch, 'url'); const stackNeedle = safe.initPattern(extraArgs.stackToMatch || '', { canNegate: true }); self.XMLHttpRequest = class extends self.XMLHttpRequest { diff --git a/src/js/resources/localstorage.js b/src/js/resources/localstorage.js index 3e33ca2397a56..69c037090437a 100644 --- a/src/js/resources/localstorage.js +++ b/src/js/resources/localstorage.js @@ -127,57 +127,6 @@ registerScriptlet(setLocalStorageItemFn, { ], }); -/******************************************************************************/ - -export function removeCacheStorageItem( - cacheNamePattern = '', - requestPattern = '' -) { - if ( cacheNamePattern === '' ) { return; } - const safe = safeSelf(); - const logPrefix = safe.makeLogPrefix('remove-cache-storage-item', cacheNamePattern, requestPattern); - const cacheStorage = self.caches; - if ( cacheStorage instanceof Object === false ) { return; } - const reCache = safe.patternToRegex(cacheNamePattern, undefined, true); - const reRequest = safe.patternToRegex(requestPattern, undefined, true); - cacheStorage.keys().then(cacheNames => { - for ( const cacheName of cacheNames ) { - if ( reCache.test(cacheName) === false ) { continue; } - if ( requestPattern === '' ) { - cacheStorage.delete(cacheName).then(result => { - if ( safe.logLevel > 1 ) { - safe.uboLog(logPrefix, `Deleting ${cacheName}`); - } - if ( result !== true ) { return; } - safe.uboLog(logPrefix, `Deleted ${cacheName}: ${result}`); - }); - continue; - } - cacheStorage.open(cacheName).then(cache => { - cache.keys().then(requests => { - for ( const request of requests ) { - if ( reRequest.test(request.url) === false ) { continue; } - if ( safe.logLevel > 1 ) { - safe.uboLog(logPrefix, `Deleting ${cacheName}/${request.url}`); - } - cache.delete(request).then(result => { - if ( result !== true ) { return; } - safe.uboLog(logPrefix, `Deleted ${cacheName}/${request.url}: ${result}`); - }); - } - }); - }); - } - }); -} -registerScriptlet(removeCacheStorageItem, { - name: 'remove-cache-storage-item.fn', - world: 'ISOLATED', - dependencies: [ - safeSelf, - ], -}); - /******************************************************************************* * * set-local-storage-item.js @@ -191,9 +140,9 @@ registerScriptlet(removeCacheStorageItem, { * **/ -export function setLocalStorageItem(key = '', value = '') { +export function setLocalStorageItem(key = '', value = '', ...varargs) { const safe = safeSelf(); - const options = safe.getExtraArgs(Array.from(arguments), 2) + const options = safe.parseVarargs(varargs) setLocalStorageItemFn('local', false, key, value, options); } registerScriptlet(setLocalStorageItem, { @@ -205,9 +154,9 @@ registerScriptlet(setLocalStorageItem, { ], }); -export function setSessionStorageItem(key = '', value = '') { +export function setSessionStorageItem(key = '', value = '', ...varargs) { const safe = safeSelf(); - const options = safe.getExtraArgs(Array.from(arguments), 2) + const options = safe.parseVarargs(varargs) setLocalStorageItemFn('session', false, key, value, options); } registerScriptlet(setSessionStorageItem, { @@ -230,9 +179,9 @@ registerScriptlet(setSessionStorageItem, { * **/ -export function trustedSetLocalStorageItem(key = '', value = '') { +export function trustedSetLocalStorageItem(key = '', value = '', ...varargs) { const safe = safeSelf(); - const options = safe.getExtraArgs(Array.from(arguments), 2) + const options = safe.parseVarargs(varargs) setLocalStorageItemFn('local', true, key, value, options); } registerScriptlet(trustedSetLocalStorageItem, { @@ -245,9 +194,9 @@ registerScriptlet(trustedSetLocalStorageItem, { ], }); -export function trustedSetSessionStorageItem(key = '', value = '') { +export function trustedSetSessionStorageItem(key = '', value = '', ...varargs) { const safe = safeSelf(); - const options = safe.getExtraArgs(Array.from(arguments), 2) + const options = safe.parseVarargs(varargs) setLocalStorageItemFn('session', true, key, value, options); } registerScriptlet(trustedSetSessionStorageItem, { diff --git a/src/js/resources/object-prune.js b/src/js/resources/object-prune.js index 50256fe52828b..537e2b2078ae1 100644 --- a/src/js/resources/object-prune.js +++ b/src/js/resources/object-prune.js @@ -163,7 +163,8 @@ function trustedPruneInboundObject( entryPoint = '', argPos = '', rawPrunePaths = '', - rawNeedlePaths = '' + rawNeedlePaths = '', + ...varargs ) { if ( entryPoint === '' ) { return; } let context = globalThis; @@ -180,7 +181,7 @@ function trustedPruneInboundObject( if ( isNaN(argIndex) ) { return; } if ( argIndex < 1 ) { return; } const safe = safeSelf(); - const extraArgs = safe.getExtraArgs(Array.from(arguments), 4); + const extraArgs = safe.parseVarargs(varargs); const needlePaths = []; if ( rawPrunePaths !== '' ) { needlePaths.push(...safe.String_split.call(rawPrunePaths, / +/)); @@ -241,11 +242,12 @@ registerScriptlet(trustedPruneInboundObject, { function trustedPruneOutboundObject( propChain = '', rawPrunePaths = '', - rawNeedlePaths = '' + rawNeedlePaths = '', + ...varargs ) { if ( propChain === '' ) { return; } const safe = safeSelf(); - const extraArgs = safe.getExtraArgs(Array.from(arguments), 3); + const extraArgs = safe.parseVarargs(varargs); proxyApplyFn(propChain, function(context) { const objBefore = context.reflect(); if ( objBefore instanceof Object === false ) { return objBefore; } diff --git a/src/js/resources/prevent-addeventlistener.js b/src/js/resources/prevent-addeventlistener.js index 885ebaa05cf59..1321edacaf9d5 100644 --- a/src/js/resources/prevent-addeventlistener.js +++ b/src/js/resources/prevent-addeventlistener.js @@ -55,10 +55,11 @@ import { safeSelf } from './safe-self.js'; function preventAddEventListener( type = '', - pattern = '' + pattern = '', + ...varargs ) { const safe = safeSelf(); - const extraArgs = safe.getExtraArgs(Array.from(arguments), 2); + const extraArgs = safe.parseVarargs(varargs); const logPrefix = safe.makeLogPrefix('prevent-addEventListener', type, pattern); const reType = safe.patternToRegex(type, undefined, true); const rePattern = safe.patternToRegex(pattern); @@ -90,8 +91,8 @@ function preventAddEventListener( return parts.join(''); }; const shouldPrevent = (thisArg, type, handler) => { - const matchesType = safe.RegExp_test.call(reType, type); - const matchesHandler = safe.RegExp_test.call(rePattern, handler); + const matchesType = safe.RegExp_test(reType, type); + const matchesHandler = safe.RegExp_test(rePattern, handler); const matchesEither = matchesType || matchesHandler; const matchesBoth = matchesType && matchesHandler; if ( safe.logLevel > 1 && matchesEither ) { @@ -125,22 +126,23 @@ function preventAddEventListener( } return context.reflect(); }; + const protect = owner => { + const { addEventListener } = owner; + Object.defineProperty(owner, 'addEventListener', { + set() { }, + get() { return addEventListener; } + }); + }; runAt(( ) => { proxyApplyFn('EventTarget.prototype.addEventListener', proxyFn); - if ( extraArgs.protect ) { - const { addEventListener } = EventTarget.prototype; - Object.defineProperty(EventTarget.prototype, 'addEventListener', { - set() { }, - get() { return addEventListener; } - }); + if ( extraArgs.protect ) { protect(EventTarget.prototype); } + if ( Object.hasOwn(document, 'addEventListener') ) { + proxyApplyFn('document.addEventListener', proxyFn); + if ( extraArgs.protect ) { protect(document); } } - proxyApplyFn('document.addEventListener', proxyFn); - if ( extraArgs.protect ) { - const { addEventListener } = document; - Object.defineProperty(document, 'addEventListener', { - set() { }, - get() { return addEventListener; } - }); + if ( Object.hasOwn(window, 'addEventListener') ) { + proxyApplyFn('window.addEventListener', proxyFn); + if ( extraArgs.protect ) { protect(window); } } }, extraArgs.runAt); } diff --git a/src/web_accessible_resources/nobab.js b/src/js/resources/prevent-bab.js similarity index 50% rename from src/web_accessible_resources/nobab.js rename to src/js/resources/prevent-bab.js index 32a2983357113..22af805919046 100644 --- a/src/web_accessible_resources/nobab.js +++ b/src/js/resources/prevent-bab.js @@ -19,8 +19,15 @@ Home: https://github.com/gorhill/uBlock */ -(function() { - 'use strict'; +import { proxyApplyFn } from './proxy-apply.js'; +import { registerScriptlet } from './base.js'; +import { safeSelf } from './safe-self.js'; + +/******************************************************************************/ + +function preventBab() { + const safe = safeSelf(); + const logPrefix = safe.makeLogPrefix('prevent-bab'); const signatures = [ [ 'blockadblock' ], [ 'babasbm' ], @@ -40,48 +47,55 @@ 'clientWidth', 'localStorage', 'Math', - 'random' + 'random', ], ]; const check = function(s) { - for ( let i = 0; i < signatures.length; i++ ) { - const tokens = signatures[i]; + if ( typeof s !== 'string' ) { return false; } + for ( const tokens of signatures ) { let match = 0; - for ( let j = 0; j < tokens.length; j++ ) { - const token = tokens[j]; - const pos = token instanceof RegExp - ? s.search(token) - : s.indexOf(token); - if ( pos !== -1 ) { match += 1; } + for ( const token of tokens ) { + const hit = token instanceof RegExp + ? token.test(s) + : s.includes(token); + if ( hit ) { match += 1; } } if ( (match / tokens.length) >= 0.8 ) { return true; } } return false; }; - window.eval = new Proxy(window.eval, { // jshint ignore: line - apply: function(target, thisArg, args) { - const a = args[0]; - if ( typeof a !== 'string' || !check(a) ) { - return target.apply(thisArg, args); - } - if ( document.body ) { - document.body.style.removeProperty('visibility'); - } - let el = document.getElementById('babasbmsgx'); - if ( el ) { - el.parentNode.removeChild(el); - } + proxyApplyFn('eval', function(context) { + const a = context.callArgs[0]; + if ( !check(a) ) { + return context.reflect(); + } + safe.uboLog(logPrefix, 'Prevented'); + if ( document.body ) { + document.body.style.removeProperty('visibility'); + } + const el = document.getElementById('babasbmsgx'); + if ( el ) { + el.parentNode.removeChild(el); } }); - window.setTimeout = new Proxy(window.setTimeout, { - apply: function(target, thisArg, args) { - const a = args[0]; - if ( - typeof a !== 'string' || - /\.bab_elementid.$/.test(a) === false - ) { - return target.apply(thisArg, args); - } + proxyApplyFn('setTimeout', function(context) { + const { callArgs } = context; + const a = callArgs[0]; + if ( typeof a === 'string' && /\.bab_elementid.$/.test(a) ) { + callArgs[0] = ( ) => { }; + safe.uboLog(logPrefix, 'Prevented'); } + return context.reflect(); }); -})(); +} +registerScriptlet(preventBab, { + name: 'prevent-bab.js', + aliases: [ + 'bab-defuser.js', + 'nobab.js', + ], + dependencies: [ + proxyApplyFn, + safeSelf, + ], +}); diff --git a/src/js/resources/prevent-clipboard-write.js b/src/js/resources/prevent-clipboard-write.js new file mode 100644 index 0000000000000..d5064a3b63439 --- /dev/null +++ b/src/js/resources/prevent-clipboard-write.js @@ -0,0 +1,149 @@ +/******************************************************************************* + + uBlock Origin - a browser extension to block requests. + Copyright (C) 2019-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock +*/ + +import { proxyApplyFn } from './proxy-apply.js'; +import { registerScriptlet } from './base.js'; +import { runAt } from './run-at.js'; +import { safeSelf } from './safe-self.js'; + +/******************************************************************************/ + +/** + * @scriptlet prevent-clipboard-write + * + * @description + * Prevent the clipboard from being overwritten. + * + * @param matches + * A pattern or regex to match against the text for the prevention to occur. + * + * @param excludeMatches + * Optional. A vararg to be used as a pattern or regex to match against the + * text for the prevention to NOT occur. + * + * @param domAlert + * Optional. A vararg to be used to alert the user in case a clipboard write + * operation was prevented. + * + * @example + * ##+js(prevent-clipboard-write, /^bash <<', + '${warning}\n', + '', + '', + ].join(''); + const domAlert = clipboardText => { + const doc = document; + const domAlert = extraArgs.domAlert.replace(/\\n/g, '\n'); + let html; + if ( domAlert.includes('${text}') ) { + const code = doc.createElement('code'); + const styles = [ + 'background-color: #ddc', + 'display: inline-block', + 'font-family: monospace', + 'font-size: 100%', + 'max-height: 8em', + 'overflow: auto', + 'padding: 0.25em', + 'user-select: all', + 'width: 100%;', + 'word-break: break-all' + ]; + if ( Boolean(extraArgs.selectable ?? true) === false ) { + styles.push('user-select: none'); + } + code.style = styles.join(';'); + code.textContent = clipboardText; + html = htmlTemplate.replace('${warning}', + domAlert.replace('${text}', code.outerHTML) + ); + } else { + html = htmlTemplate.replace('${warning}', domAlert); + } + if ( currentAlert ) { currentAlert.remove(); } + const domParser = new DOMParser(); + const fragment = domParser.parseFromString(html, 'text/html'); + currentAlert = fragment.querySelector('div'); + const button = currentAlert.querySelector('button'); + button.addEventListener('click', ( ) => { + if ( currentAlert === null ) { return; } + currentAlert.remove(); + currentAlert = null; + }); + doc.documentElement.append(currentAlert); + }; + let currentAlert = null; + const prevent = text => { + if ( typeof text !== 'string' ) { return; } + text = text.trim(); + if ( safe.testPattern(pattern, text) !== true ) { return; } + if ( extraArgs.excludeMatches ) { + if ( safe.testPattern(excludePattern, text) ) { return; } + } + if ( extraArgs.domAlert ) { + domAlert(text); + } + safe.uboLog(logPrefix, 'Prevented:\n\t', text); + return true; + }; + const installTraps = ( ) => { + proxyApplyFn('navigator.clipboard.writeText', async function(context) { + const text = `${context.callArgs[0]}`; + if ( prevent(text) ) { return; } + return context.reflect(); + }, { skipToString: true }); + proxyApplyFn('document.execCommand', function(context) { + const { callArgs } = context; + if ( callArgs[0] === 'copy' || callArgs[0] === 'cut' ) { + const text = document.getSelection()?.toString(); + if ( prevent(text) ) { return true; } + } + return context.reflect(); + }, { skipToString: true }); + }; + runAt(( ) => { + self.document.addEventListener('mousemove', installTraps, { + once: true, + capture: true, + }); + }, 'interactive') +} +registerScriptlet(preventClipboardWrite, { + name: 'prevent-clipboard-write.js', + requiresTrust: true, + dependencies: [ + proxyApplyFn, + runAt, + safeSelf, + ], +}); diff --git a/src/js/resources/prevent-fetch.js b/src/js/resources/prevent-fetch.js index dbe096a5dbc7c..d636859b63d31 100644 --- a/src/js/resources/prevent-fetch.js +++ b/src/js/resources/prevent-fetch.js @@ -36,7 +36,8 @@ function preventFetchFn( trusted = false, propsToMatch = '', responseBody = '', - responseType = '' + responseType = '', + ...varargs ) { const safe = safeSelf(); const setTimeout = self.setTimeout; @@ -47,7 +48,7 @@ function preventFetchFn( responseBody, responseType ); - const extraArgs = safe.getExtraArgs(Array.from(arguments), 4); + const extraArgs = safe.parseVarargs(varargs); const propNeedles = parsePropertiesToMatchFn(propsToMatch, 'url'); const validResponseProps = { ok: [ false, true ], diff --git a/src/js/resources/prevent-innerHTML.js b/src/js/resources/prevent-innerHTML.js index 5c92748768975..1e14c2ae1742d 100644 --- a/src/js/resources/prevent-innerHTML.js +++ b/src/js/resources/prevent-innerHTML.js @@ -52,12 +52,15 @@ function freezeElementProperty( const logPrefix = safe.makeLogPrefix('freeze-element-property', property, selector, pattern); const matcher = safe.initPattern(pattern, { canNegate: true }); const owner = (( ) => { - if ( Object.hasOwn(Element.prototype, property) ) { - return Element.prototype; + if ( Object.hasOwn(HTMLScriptElement.prototype, property) ) { + return HTMLScriptElement.prototype; } if ( Object.hasOwn(HTMLElement.prototype, property) ) { return HTMLElement.prototype; } + if ( Object.hasOwn(Element.prototype, property) ) { + return Element.prototype; + } if ( Object.hasOwn(Node.prototype, property) ) { return Node.prototype; } diff --git a/src/js/resources/prevent-xhr.js b/src/js/resources/prevent-xhr.js index e25a7e895439d..478470872a70f 100644 --- a/src/js/resources/prevent-xhr.js +++ b/src/js/resources/prevent-xhr.js @@ -25,7 +25,10 @@ import { matchObjectPropertiesFn, parsePropertiesToMatchFn, } from './utils.js'; -import { proxyApplyFn } from './proxy-apply.js'; +import { + proxyApplyFn, + proxyToStringFn, +} from './proxy-apply.js'; import { registerScriptlet } from './base.js'; import { safeSelf } from './safe-self.js'; @@ -34,6 +37,62 @@ import { safeSelf } from './safe-self.js'; /******************************************************************************/ +export function modifyXhrResponseFn( + propsToMatch = '', + modifierFn = '' +) { + if ( typeof propsToMatch !== 'string' ) { return; } + const safe = safeSelf(); + if ( modifyXhrResponseFn.xhrInstances === undefined ) { + modifyXhrResponseFn.xhrInstances = new WeakMap(); + } + const propNeedles = parsePropertiesToMatchFn(propsToMatch, 'url'); + const NativeXMLHttpRequest = self.XMLHttpRequest; + const TrappedXMLHttpRequest = class XMLHttpRequest extends NativeXMLHttpRequest { + open(method, url, ...args) { + const haystack = { method, url }; + if ( propsToMatch === '' ) { + safe.uboLog(`modifyXhrResponseFn() / Called: ${safe.JSON_stringify(haystack, null, 2)}`); + } else if ( matchObjectPropertiesFn(propNeedles, haystack) ) { + modifyXhrResponseFn.xhrInstances.set(this, modifierFn); + } + return super.open(method, url, ...args); + } + get response() { + const modifierFn = modifyXhrResponseFn.xhrInstances.get(this); + return modifierFn + ? modifierFn(this, super.response) + : super.response; + } + get responseText() { + const modifierFn = modifyXhrResponseFn.xhrInstances.get(this); + return modifierFn + ? modifierFn(this, super.responseText) + : super.responseText; + } + get responseXML() { + const modifierFn = modifyXhrResponseFn.xhrInstances.get(this); + return modifierFn + ? modifierFn(this, super.responseXML) + : super.responseXML; + } + }; + proxyToStringFn(TrappedXMLHttpRequest.prototype.open, NativeXMLHttpRequest.prototype.open); + proxyToStringFn(TrappedXMLHttpRequest, NativeXMLHttpRequest); + self.XMLHttpRequest = TrappedXMLHttpRequest; +} +registerScriptlet(modifyXhrResponseFn, { + name: 'modify-xhr-response.fn', + dependencies: [ + matchObjectPropertiesFn, + parsePropertiesToMatchFn, + proxyToStringFn, + safeSelf, + ], +}); + +/******************************************************************************/ + function preventXhrFn( trusted = false, propsToMatch = '', @@ -230,7 +289,7 @@ registerScriptlet(preventXhrFn, { * */ function preventXhr(...args) { - return preventXhrFn(false, ...args); + preventXhrFn(false, ...args); } registerScriptlet(preventXhr, { name: 'prevent-xhr.js', @@ -260,7 +319,7 @@ registerScriptlet(preventXhr, { * */ function trustedPreventXhr(...args) { - return preventXhrFn(true, ...args); + preventXhrFn(true, ...args); } registerScriptlet(trustedPreventXhr, { name: 'trusted-prevent-xhr.js', diff --git a/src/js/resources/proxy-apply.js b/src/js/resources/proxy-apply.js index 125e4300a5770..9f32a643ff387 100644 --- a/src/js/resources/proxy-apply.js +++ b/src/js/resources/proxy-apply.js @@ -24,9 +24,36 @@ import { registerScriptlet } from './base.js'; /******************************************************************************/ +export function proxyToStringFn(proxiedFn, nativeFn) { + if ( proxyToStringFn.proxies === undefined ) { + proxyToStringFn.proxies = new WeakMap(); + proxyToStringFn.nativeToString = Function.prototype.toString; + const proxiedToString = new Proxy(Function.prototype.toString, { + apply(target, thisArg) { + let proxied = thisArg; + for(;;) { + const fn = proxyToStringFn.proxies.get(proxied); + if ( fn === undefined ) { break; } + proxied = fn; + } + return proxyToStringFn.nativeToString.call(proxied); + } + }); + proxyToStringFn.proxies.set(proxiedToString, proxyToStringFn.nativeToString); + Function.prototype.toString = proxiedToString; + } + proxyToStringFn.proxies.set(proxiedFn, nativeFn); +} +registerScriptlet(proxyToStringFn, { + name: 'proxy-tostring.fn', +}); + +/******************************************************************************/ + export function proxyApplyFn( target = '', - handler = '' + handler = '', + options = {} ) { let context = globalThis; let prop = target; @@ -87,20 +114,22 @@ export function proxyApplyFn( }; proxyApplyFn.isCtor = new Map(); proxyApplyFn.proxies = new WeakMap(); - proxyApplyFn.nativeToString = Function.prototype.toString; - const proxiedToString = new Proxy(Function.prototype.toString, { - apply(target, thisArg) { - let proxied = thisArg; - for(;;) { - const fn = proxyApplyFn.proxies.get(proxied); - if ( fn === undefined ) { break; } - proxied = fn; + if ( (options.skipToString || proxyApplyFn.skipToString) !== true ) { + proxyApplyFn.nativeToString = Function.prototype.toString; + const proxiedToString = new Proxy(Function.prototype.toString, { + apply(target, thisArg) { + let proxied = thisArg; + for(;;) { + const fn = proxyApplyFn.proxies.get(proxied); + if ( fn === undefined ) { break; } + proxied = fn; + } + return proxyApplyFn.nativeToString.call(proxied); } - return proxyApplyFn.nativeToString.call(proxied); - } - }); - proxyApplyFn.proxies.set(proxiedToString, proxyApplyFn.nativeToString); - Function.prototype.toString = proxiedToString; + }); + proxyApplyFn.proxies.set(proxiedToString, proxyApplyFn.nativeToString); + Function.prototype.toString = proxiedToString; + } } if ( proxyApplyFn.isCtor.has(target) === false ) { proxyApplyFn.isCtor.set(target, fn.prototype?.constructor === fn); @@ -122,3 +151,19 @@ export function proxyApplyFn( registerScriptlet(proxyApplyFn, { name: 'proxy-apply.fn', }); + +/******************************************************************************/ + +export function proxyApplyConfig(config = '') { + try { + if ( typeof proxyApplyFn !== 'function' ) { return; } + config = JSON.parse(config); + if ( typeof config !== 'object' ) { return; } + Object.assign(proxyApplyFn, config); + } catch { + } +} +registerScriptlet(proxyApplyConfig , { + name: 'proxy-apply-config.js', + priority: 100, +}); diff --git a/src/js/resources/replace-argument.js b/src/js/resources/replace-argument.js index 1a305389bf5ce..0c98217a44e02 100644 --- a/src/js/resources/replace-argument.js +++ b/src/js/resources/replace-argument.js @@ -60,13 +60,14 @@ import { validateConstantFn } from './set-constant.js'; export function trustedReplaceArgument( propChain = '', argposRaw = '', - argraw = '' + argraw = '', + ...varargs ) { if ( propChain === '' ) { return; } const safe = safeSelf(); const logPrefix = safe.makeLogPrefix('trusted-replace-argument', propChain, argposRaw, argraw); const argoffset = parseInt(argposRaw, 10) || 0; - const extraArgs = safe.getExtraArgs(Array.from(arguments), 3); + const extraArgs = safe.parseVarargs(varargs); let replacer; if ( argraw.startsWith('repl:/') ) { const parsed = parseReplaceFn(argraw.slice(5)); @@ -82,7 +83,7 @@ export function trustedReplaceArgument( replacer = ( ) => value; } const reCondition = extraArgs.condition - ? safe.patternToRegex(extraArgs.condition) + ? safe.patternToRegex(`${extraArgs.condition}`) : /^/; const getArg = context => { if ( argposRaw === 'this' ) { return context.thisArg; } @@ -108,7 +109,7 @@ export function trustedReplaceArgument( } const argBefore = getArg(context); if ( extraArgs.condition !== undefined ) { - if ( safe.RegExp_test.call(reCondition, argBefore) === false ) { + if ( safe.RegExp_test(reCondition, argBefore) === false ) { return context.reflect(); } } diff --git a/src/js/resources/safe-self.js b/src/js/resources/safe-self.js index 096f3c21d73b4..19a06f9404916 100644 --- a/src/js/resources/safe-self.js +++ b/src/js/resources/safe-self.js @@ -28,15 +28,14 @@ import { registerScriptlet } from './base.js'; /* global scriptletGlobals */ export function safeSelf() { - if ( scriptletGlobals.safeSelf ) { - return scriptletGlobals.safeSelf; + if ( safeSelf.safe ) { + return safeSelf.safe; } const self = globalThis; const safe = { 'Array_from': Array.from, 'Error': self.Error, - 'Function_toStringFn': self.Function.prototype.toString, - 'Function_toString': thisArg => safe.Function_toStringFn.call(thisArg), + 'Function_toString': Function.prototype.call.bind(self.Function.prototype.toString), 'Math_floor': Math.floor, 'Math_max': Math.max, 'Math_min': Math.min, @@ -49,7 +48,7 @@ export function safeSelf() { 'Object_hasOwn': Object.hasOwn.bind(Object), 'Object_toString': Object.prototype.toString, 'RegExp': self.RegExp, - 'RegExp_test': self.RegExp.prototype.test, + 'RegExp_test': Function.prototype.call.bind(self.RegExp.prototype.test), 'RegExp_exec': self.RegExp.prototype.exec, 'Request_clone': self.Request.prototype.clone, 'String': self.String, @@ -60,10 +59,8 @@ export function safeSelf() { 'removeEventListener': self.EventTarget.prototype.removeEventListener, 'fetch': self.fetch, 'JSON': self.JSON, - 'JSON_parseFn': self.JSON.parse, - 'JSON_stringifyFn': self.JSON.stringify, - 'JSON_parse': (...args) => safe.JSON_parseFn.call(safe.JSON, ...args), - 'JSON_stringify': (...args) => safe.JSON_stringifyFn.call(safe.JSON, ...args), + 'JSON_parse': Function.prototype.call.bind(self.JSON.parse, self.JSON), + 'JSON_stringify': Function.prototype.call.bind(self.JSON.stringify, self.JSON), 'log': console.log.bind(console), // Properties logLevel: 0, @@ -116,7 +113,7 @@ export function safeSelf() { testPattern(details, haystack) { if ( details.matchAll ) { return true; } if ( details.re ) { - return this.RegExp_test.call(details.re, haystack) === details.expect; + return this.RegExp_test(details.re, haystack) === details.expect; } return haystack.includes(details.pattern) === details.expect; }, @@ -134,33 +131,20 @@ export function safeSelf() { } return /^/; }, - getExtraArgs(args, offset = 0) { - const entries = args.slice(offset).reduce((out, v, i, a) => { - if ( (i & 1) === 0 ) { - const rawValue = a[i+1]; - const value = /^\d+$/.test(rawValue) - ? parseInt(rawValue, 10) - : rawValue; - out.push([ a[i], value ]); - } + parseVarargs(varargs) { + const entries = varargs.reduce((out, v, i, a) => { + if ( i & 1 ) { return out; } + const rawValue = a[i+1]; + const value = /^\d+$/.test(rawValue) + ? parseInt(rawValue, 10) + : rawValue; + out.push([ a[i], value ]); return out; }, []); return this.Object_fromEntries(entries); }, - onIdle(fn, options) { - if ( self.requestIdleCallback ) { - return self.requestIdleCallback(fn, options); - } - return self.requestAnimationFrame(fn); - }, - offIdle(id) { - if ( self.requestIdleCallback ) { - return self.cancelIdleCallback(id); - } - return self.cancelAnimationFrame(id); - } }; - scriptletGlobals.safeSelf = safe; + safeSelf.safe = safe; if ( scriptletGlobals.bcSecret === undefined ) { return safe; } // This is executed only when the logger is opened safe.logLevel = scriptletGlobals.logLevel || 1; diff --git a/src/js/resources/scriptlets.js b/src/js/resources/scriptlets.js index b86d645a85747..cc733487d75aa 100755 --- a/src/js/resources/scriptlets.js +++ b/src/js/resources/scriptlets.js @@ -20,6 +20,7 @@ */ +import './abort-current-script.js'; import './attribute.js'; import './create-html.js'; import './href-sanitizer.js'; @@ -28,35 +29,40 @@ import './json-prune.js'; import './noeval.js'; import './object-prune.js'; import './prevent-addeventlistener.js'; +import './prevent-bab.js'; +import './prevent-clipboard-write.js'; import './prevent-dialog.js'; import './prevent-fetch.js'; import './prevent-innerHTML.js'; import './prevent-navigation.js'; import './prevent-settimeout.js'; -import './prevent-xhr.js'; import './replace-argument.js'; import './spoof-css.js'; +import './vod.js'; import { collateFetchArgumentsFn, getExceptionTokenFn, getRandomTokenFn, + lookupElementsFn, matchObjectPropertiesFn, + onIdleFn, parsePropertiesToMatchFn, } from './utils.js'; -import { runAt, runAtHtmlElementFn } from './run-at.js'; +import { + runAt, + runAtHtmlElementFn, +} from './run-at.js'; import { getAllCookiesFn } from './cookie.js'; import { getAllLocalStorageFn } from './localstorage.js'; import { matchesStackTraceFn } from './stack-trace.js'; +import { modifyXhrResponseFn } from './prevent-xhr.js'; import { proxyApplyFn } from './proxy-apply.js'; import { registeredScriptlets } from './base.js'; import { safeSelf } from './safe-self.js'; import { validateConstantFn } from './set-constant.js'; -// Externally added to the private namespace in which scriptlets execute. -/* global scriptletGlobals */ - /* eslint no-prototype-builtins: 0 */ export const builtinScriptlets = registeredScriptlets; @@ -67,137 +73,6 @@ export const builtinScriptlets = registeredScriptlets; These are meant to be used as dependencies to injectable scriptlets. -*******************************************************************************/ - -builtinScriptlets.push({ - name: 'should-debug.fn', - fn: shouldDebug, -}); -function shouldDebug(details) { - if ( details instanceof Object === false ) { return false; } - return scriptletGlobals.canDebug && details.debug; -} - -/******************************************************************************/ - -builtinScriptlets.push({ - name: 'abort-current-script.fn', - fn: abortCurrentScriptFn, - dependencies: [ - 'get-exception-token.fn', - 'safe-self.fn', - 'should-debug.fn', - ], -}); -// Issues to mind before changing anything: -// https://github.com/uBlockOrigin/uBlock-issues/issues/2154 -function abortCurrentScriptFn( - target = '', - needle = '', - context = '' -) { - if ( typeof target !== 'string' ) { return; } - if ( target === '' ) { return; } - const safe = safeSelf(); - const logPrefix = safe.makeLogPrefix('abort-current-script', target, needle, context); - const reNeedle = safe.patternToRegex(needle); - const reContext = safe.patternToRegex(context); - const extraArgs = safe.getExtraArgs(Array.from(arguments), 3); - const thisScript = document.currentScript; - const chain = safe.String_split.call(target, '.'); - let owner = window; - let prop; - for (;;) { - prop = chain.shift(); - if ( chain.length === 0 ) { break; } - if ( prop in owner === false ) { break; } - owner = owner[prop]; - if ( owner instanceof Object === false ) { return; } - } - let value; - let desc = Object.getOwnPropertyDescriptor(owner, prop); - if ( - desc instanceof Object === false || - desc.get instanceof Function === false - ) { - value = owner[prop]; - desc = undefined; - } - const debug = shouldDebug(extraArgs); - const exceptionToken = getExceptionTokenFn(); - const scriptTexts = new WeakMap(); - const textContentGetter = Object.getOwnPropertyDescriptor(Node.prototype, 'textContent').get; - const getScriptText = elem => { - let text = textContentGetter.call(elem); - if ( text.trim() !== '' ) { return text; } - if ( scriptTexts.has(elem) ) { return scriptTexts.get(elem); } - const [ , mime, content ] = - /^data:([^,]*),(.+)$/.exec(elem.src.trim()) || - [ '', '', '' ]; - try { - switch ( true ) { - case mime.endsWith(';base64'): - text = self.atob(content); - break; - default: - text = self.decodeURIComponent(content); - break; - } - } catch { - } - scriptTexts.set(elem, text); - return text; - }; - const validate = ( ) => { - const e = document.currentScript; - if ( e instanceof HTMLScriptElement === false ) { return; } - if ( e === thisScript ) { return; } - if ( context !== '' && reContext.test(e.src) === false ) { - // eslint-disable-next-line no-debugger - if ( debug === 'nomatch' || debug === 'all' ) { debugger; } - return; - } - if ( safe.logLevel > 1 && context !== '' ) { - safe.uboLog(logPrefix, `Matched src\n${e.src}`); - } - const scriptText = getScriptText(e); - if ( reNeedle.test(scriptText) === false ) { - // eslint-disable-next-line no-debugger - if ( debug === 'nomatch' || debug === 'all' ) { debugger; } - return; - } - if ( safe.logLevel > 1 ) { - safe.uboLog(logPrefix, `Matched text\n${scriptText}`); - } - // eslint-disable-next-line no-debugger - if ( debug === 'match' || debug === 'all' ) { debugger; } - safe.uboLog(logPrefix, 'Aborted'); - throw new ReferenceError(exceptionToken); - }; - // eslint-disable-next-line no-debugger - if ( debug === 'install' ) { debugger; } - try { - Object.defineProperty(owner, prop, { - get: function() { - validate(); - return desc instanceof Object - ? desc.get.call(owner) - : value; - }, - set: function(a) { - validate(); - if ( desc instanceof Object ) { - desc.set.call(owner, a); - } else { - value = a; - } - } - }); - } catch(ex) { - safe.uboErr(logPrefix, `Error: ${ex}`); - } -} - /******************************************************************************/ builtinScriptlets.push({ @@ -212,28 +87,20 @@ builtinScriptlets.push({ function replaceNodeTextFn( nodeName = '', pattern = '', - replacement = '' + replacement = '', + ...varargs ) { const safe = safeSelf(); const logPrefix = safe.makeLogPrefix('replace-node-text.fn', ...Array.from(arguments)); const reNodeName = safe.patternToRegex(nodeName, 'i', true); const rePattern = safe.patternToRegex(pattern, 'gms'); - const extraArgs = safe.getExtraArgs(Array.from(arguments), 3); + const extraArgs = safe.parseVarargs(varargs); const reIncludes = extraArgs.includes || extraArgs.condition ? safe.patternToRegex(extraArgs.includes || extraArgs.condition, 'ms') : null; const reExcludes = extraArgs.excludes ? safe.patternToRegex(extraArgs.excludes, 'ms') : null; - const stop = (takeRecord = true) => { - if ( takeRecord ) { - handleMutations(observer.takeRecords()); - } - observer.disconnect(); - if ( safe.logLevel > 1 ) { - safe.uboLog(logPrefix, 'Quitting'); - } - }; const textContentFactory = (( ) => { const out = { createScript: s => s }; const { trustedTypes: tt } = self; @@ -246,19 +113,19 @@ function replaceNodeTextFn( } return out; })(); - let sedCount = extraArgs.sedCount || 0; + let sedCount = extraArgs.sedCount ?? Number.MAX_SAFE_INTEGER; const handleNode = node => { const before = node.textContent; if ( reIncludes ) { reIncludes.lastIndex = 0; - if ( safe.RegExp_test.call(reIncludes, before) === false ) { return true; } + if ( safe.RegExp_test(reIncludes, before) === false ) { return; } } if ( reExcludes ) { reExcludes.lastIndex = 0; - if ( safe.RegExp_test.call(reExcludes, before) ) { return true; } + if ( safe.RegExp_test(reExcludes, before) ) { return; } } rePattern.lastIndex = 0; - if ( safe.RegExp_test.call(rePattern, before) === false ) { return true; } + if ( safe.RegExp_test(rePattern, before) === false ) { return; } rePattern.lastIndex = 0; const after = pattern !== '' ? before.replace(rePattern, replacement) @@ -270,44 +137,65 @@ function replaceNodeTextFn( safe.uboLog(logPrefix, `Text before:\n${before.trim()}`); } safe.uboLog(logPrefix, `Text after:\n${after.trim()}`); - return sedCount === 0 || (sedCount -= 1) !== 0; + sedCount -= 1; }; - const handleMutations = mutations => { - for ( const mutation of mutations ) { - for ( const node of mutation.addedNodes ) { - if ( reNodeName.test(node.nodeName) === false ) { continue; } - if ( handleNode(node) ) { continue; } - stop(false); return; - } - } - }; - const observer = new MutationObserver(handleMutations); - observer.observe(document, { childList: true, subtree: true }); - if ( document.documentElement ) { - const treeWalker = document.createTreeWalker( - document.documentElement, + const handleTree = root => { + const treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT ); + const { currentScript } = document; let count = 0; for (;;) { const node = treeWalker.nextNode(); - count += 1; if ( node === null ) { break; } - if ( reNodeName.test(node.nodeName) === false ) { continue; } - if ( node === document.currentScript ) { continue; } - if ( handleNode(node) ) { continue; } - stop(); break; + count += 1; + if ( node === currentScript ) { continue; } + if ( reNodeName.test(node.nodeName) ) { + handleNode(node); + } else if ( node.nodeName === 'TEMPLATE' ) { + count += handleTree(node.content); + } else { + continue; + } + if ( sedCount === 0 ) { break; } } + return count; + }; + if ( document.documentElement ) { + const count = handleTree(document.documentElement); safe.uboLog(logPrefix, `${count} nodes present before installing mutation observer`); } - if ( extraArgs.stay ) { return; } - runAt(( ) => { - const quitAfter = extraArgs.quitAfter || 0; - if ( quitAfter !== 0 ) { - setTimeout(( ) => { stop(); }, quitAfter); - } else { - stop(); + const stay = Boolean(extraArgs.stay); + if ( sedCount === 0 && stay === false ) { return; } + const stop = (takeRecord = true) => { + const mutations = takeRecord ? observer.takeRecords() : []; + observer.disconnect(); + handleMutations(mutations); + if ( safe.logLevel > 1 ) { + safe.uboLog(logPrefix, 'Quitting'); } + }; + const handleMutations = mutations => { + for ( const mutation of mutations ) { + for ( const node of mutation.addedNodes ) { + if ( reNodeName.test(node.nodeName) ) { + handleNode(node); + } else if ( node.nodeName === 'TEMPLATE' ) { + handleTree(node.content); + } else { + continue; + } + if ( sedCount === 0 ) { return stop(false); } + } + } + }; + const observer = new MutationObserver(handleMutations); + observer.observe(document, { childList: true, subtree: true }); + if ( stay ) { return; } + runAt(( ) => { + const quitAfter = extraArgs.quitAfter ?? 0; + if ( quitAfter === 0 ) { return stop(); } + setTimeout(( ) => { stop(); }, quitAfter); }, 'interactive'); } @@ -327,7 +215,8 @@ function replaceFetchResponseFn( trusted = false, pattern = '', replacement = '', - propsToMatch = '' + propsToMatch = '', + ...varargs ) { if ( trusted !== true ) { return; } const safe = safeSelf(); @@ -335,7 +224,7 @@ function replaceFetchResponseFn( if ( pattern === '*' ) { pattern = '.*'; } const rePattern = safe.patternToRegex(pattern); const propNeedles = parsePropertiesToMatchFn(propsToMatch, 'url'); - const extraArgs = safe.getExtraArgs(Array.from(arguments), 4); + const extraArgs = safe.parseVarargs(varargs); const reIncludes = extraArgs.includes ? safe.patternToRegex(extraArgs.includes) : null; self.fetch = new Proxy(self.fetch, { apply: function(target, thisArg, args) { @@ -390,29 +279,6 @@ function replaceFetchResponseFn( These are meant to be used in the MAIN (webpage) execution world. -*******************************************************************************/ - -builtinScriptlets.push({ - name: 'abort-current-script.js', - aliases: [ - 'acs.js', - 'abort-current-inline-script.js', - 'acis.js', - ], - fn: abortCurrentScript, - dependencies: [ - 'abort-current-script.fn', - 'run-at-html-element.fn', - ], -}); -// Issues to mind before changing anything: -// https://github.com/uBlockOrigin/uBlock-issues/issues/2154 -function abortCurrentScript(...args) { - runAtHtmlElementFn(( ) => { - abortCurrentScriptFn(...args); - }); -} - /******************************************************************************/ builtinScriptlets.push({ @@ -668,6 +534,7 @@ builtinScriptlets.push({ fn: removeClass, world: 'ISOLATED', dependencies: [ + 'on-idle.fn', 'run-at.fn', 'safe-self.fn', ], @@ -718,7 +585,7 @@ function removeClass( } } if ( skip ) { return; } - timer = safe.onIdle(rmclass, { timeout: 67 }); + timer = onIdleFn(rmclass, { timeout: 67 }); }; const observer = new MutationObserver(mutationHandler); const start = ( ) => { @@ -1133,20 +1000,22 @@ builtinScriptlets.push({ name: 'xml-prune.js', fn: xmlPrune, dependencies: [ + 'modify-xhr-response.fn', 'safe-self.fn', ], }); function xmlPrune( selector = '', selectorCheck = '', - urlPattern = '' + urlPattern = '', + ...varargs ) { if ( typeof selector !== 'string' ) { return; } if ( selector === '' ) { return; } const safe = safeSelf(); const logPrefix = safe.makeLogPrefix('xml-prune', selector, selectorCheck, urlPattern); const reUrl = safe.patternToRegex(urlPattern); - const extraArgs = safe.getExtraArgs(Array.from(arguments), 3); + const extraArgs = safe.parseVarargs(varargs); const queryAll = (xmlDoc, selector) => { const isXpath = /^xpath\(.+\)$/.test(selector); if ( isXpath === false ) { @@ -1237,41 +1106,14 @@ function xmlPrune( }); } }); - self.XMLHttpRequest.prototype.open = new Proxy(self.XMLHttpRequest.prototype.open, { - apply: async (target, thisArg, args) => { - if ( reUrl.test(urlFromArg(args[1])) === false ) { - return Reflect.apply(target, thisArg, args); - } - thisArg.addEventListener('readystatechange', function() { - if ( thisArg.readyState !== 4 ) { return; } - const type = thisArg.responseType; - if ( - type === 'document' || - type === '' && thisArg.responseXML instanceof XMLDocument - ) { - pruneFromDoc(thisArg.responseXML); - const serializer = new XMLSerializer(); - const textout = serializer.serializeToString(thisArg.responseXML); - Object.defineProperty(thisArg, 'responseText', { value: textout }); - if ( typeof thisArg.response === 'string' ) { - Object.defineProperty(thisArg, 'response', { value: textout }); - } - return; - } - if ( - type === 'text' || - type === '' && typeof thisArg.responseText === 'string' - ) { - const textin = thisArg.responseText; - const textout = pruneFromText(textin); - if ( textout === textin ) { return; } - Object.defineProperty(thisArg, 'response', { value: textout }); - Object.defineProperty(thisArg, 'responseText', { value: textout }); - return; - } - }); - return Reflect.apply(target, thisArg, args); + modifyXhrResponseFn(urlPattern, (xhr, before) => { + if ( before instanceof XMLDocument ) { + return pruneFromDoc(before); + } + if ( typeof before === 'string' ) { + return pruneFromText(before); } + return before; }); } @@ -1613,6 +1455,24 @@ function multiup() { document.addEventListener('click', handler, { capture: true }); } +/******************************************************************************/ + +builtinScriptlets.push({ + name: 'break-on-call.js', + fn: breakOnCall, + dependencies: [ + 'proxy-apply.fn', + ], +}); +function breakOnCall(target) { + proxyApplyFn(target, function(context) { + debugger; // eslint-disable-line no-debugger + return context.reflect(); + }); +} + + + /******************************************************************************* @@ -1716,7 +1576,8 @@ builtinScriptlets.push({ function trustedReplaceXhrResponse( pattern = '', replacement = '', - propsToMatch = '' + propsToMatch = '', + ...varargs ) { const safe = safeSelf(); const logPrefix = safe.makeLogPrefix('trusted-replace-xhr-response', pattern, replacement, propsToMatch); @@ -1724,7 +1585,7 @@ function trustedReplaceXhrResponse( if ( pattern === '*' ) { pattern = '.*'; } const rePattern = safe.patternToRegex(pattern); const propNeedles = parsePropertiesToMatchFn(propsToMatch, 'url'); - const extraArgs = safe.getExtraArgs(Array.from(arguments), 3); + const extraArgs = safe.parseVarargs(varargs); const reIncludes = extraArgs.includes ? safe.patternToRegex(extraArgs.includes) : null; self.XMLHttpRequest = class extends self.XMLHttpRequest { open(method, url, ...args) { @@ -1785,10 +1646,27 @@ function trustedReplaceXhrResponse( /******************************************************************************* * - * trusted-click-element.js + * @scriptlet trusted-click-element * - * Reference API: - * https://github.com/AdguardTeam/Scriptlets/blob/master/src/scriptlets/trusted-click-element.ts + * @description + * Programmatically click on one or more elements. + * + * @param steps + * A comma-separated list of steps to fulfilled: + * - A valid CSS selector matching an element to programmatically click + * - A integer: A delay in milliseconds to wait before the next step is + * processed. If the last step is an integer, it is used as a timeout value + * before the scriptlet bails out (default to 11s) + * If the list of steps starts with `;` or `|`, it will be used as the + * separator character instead of comma. This is convenient when a selector + * contains a comma character. + * A selector must be one of: + * - A valid plain CSS selector + * - An xpath expression: xpath:[expression] + * Addtionally: + * - Use `>>>` between selectors to target an element inside a shadow root + * - Prepend with `when-visible:[selector]` to progrmatically click the element + * only when it is visible * **/ @@ -1800,6 +1678,7 @@ builtinScriptlets.push({ dependencies: [ 'get-all-cookies.fn', 'get-all-local-storage.fn', + 'lookup-elements.fn', 'run-at-html-element.fn', 'safe-self.fn', ], @@ -1856,35 +1735,16 @@ function trustedClickElement( } } - const getShadowRoot = elem => { - // Firefox - if ( elem.openOrClosedShadowRoot ) { - return elem.openOrClosedShadowRoot; - } - // Chromium - if ( typeof chrome === 'object' ) { - if ( chrome.dom && chrome.dom.openOrClosedShadowRoot ) { - return chrome.dom.openOrClosedShadowRoot(elem); - } - } - return elem.shadowRoot; - }; - - const querySelectorEx = (selector, context = document) => { - const pos = selector.indexOf(' >>> '); - if ( pos === -1 ) { return context.querySelector(selector); } - const outside = selector.slice(0, pos).trim(); - const inside = selector.slice(pos + 5).trim(); - const elem = context.querySelector(outside); - if ( elem === null ) { return null; } - const shadowRoot = getShadowRoot(elem); - return shadowRoot && querySelectorEx(inside, shadowRoot); - }; - - const steps = safe.String_split.call(selectors, /\s*,\s*/).map(a => { - if ( /^\d+$/.test(a) ) { return parseInt(a, 10); } - return a; - }); + const steps = (( ) => { + const steps = /^[;|]/.test(selectors) + ? safe.String_split.call(selectors.slice(1), selectors.charAt(0)) + : safe.String_split.call(selectors, ','); + return steps.map(a => { + a = a.trim(); + if ( /^\d+$/.test(a) ) { return parseInt(a, 10); } + return a; + }); + })(); if ( steps.length === 0 ) { return; } const clickDelay = parseInt(delay, 10) || 1; for ( let i = steps.length-1; i > 0; i-- ) { @@ -1896,9 +1756,11 @@ function trustedClickElement( steps.unshift(clickDelay); } if ( typeof steps.at(-1) !== 'number' ) { - steps.push(10000); + steps.push(11000); } + const timeout = steps.pop(); + const waitForTime = ms => { return new Promise(resolve => { safe.uboLog(logPrefix, `Waiting for ${ms} ms`); @@ -1908,66 +1770,18 @@ function trustedClickElement( }, ms); }); }; - waitForTime.cancel = ( ) => { - const { timer } = waitForTime; - if ( timer === undefined ) { return; } - clearTimeout(timer); - waitForTime.timer = undefined; - }; - const waitForElement = selector => { - return new Promise(resolve => { - const elem = querySelectorEx(selector); - if ( elem !== null ) { - elem.click(); - resolve(); - return; - } - safe.uboLog(logPrefix, `Waiting for ${selector}`); - const observer = new MutationObserver(( ) => { - const elem = querySelectorEx(selector); - if ( elem === null ) { return; } - waitForElement.cancel(); - elem.click(); - resolve(); - }); - observer.observe(document, { - attributes: true, - childList: true, - subtree: true, - }); - waitForElement.observer = observer; + const waitForElement = directive => { + safe.uboLog(logPrefix, `Waiting for ${directive}`); + return lookupElementsFn(directive, Date.now() + timeout).then(elems => { + if ( elems.length === 0 ) { return false; } + elems[0].click(); + safe.uboLog(logPrefix, `Clicked ${directive}`); + return true; }); }; - waitForElement.cancel = ( ) => { - const { observer } = waitForElement; - if ( observer === undefined ) { return; } - waitForElement.observer = undefined; - observer.disconnect(); - }; - - const waitForTimeout = ms => { - waitForTimeout.cancel(); - waitForTimeout.timer = setTimeout(( ) => { - waitForTimeout.timer = undefined; - terminate(); - safe.uboLog(logPrefix, `Timed out after ${ms} ms`); - }, ms); - }; - waitForTimeout.cancel = ( ) => { - if ( waitForTimeout.timer === undefined ) { return; } - clearTimeout(waitForTimeout.timer); - waitForTimeout.timer = undefined; - }; - - const terminate = ( ) => { - waitForTime.cancel(); - waitForElement.cancel(); - waitForTimeout.cancel(); - }; const process = async ( ) => { - waitForTimeout(steps.pop()); while ( steps.length !== 0 ) { const step = steps.shift(); if ( step === undefined ) { break; } @@ -1977,10 +1791,11 @@ function trustedClickElement( continue; } if ( step.startsWith('!') ) { continue; } - await waitForElement(step); - safe.uboLog(logPrefix, `Clicked ${step}`); + const clicked = await waitForElement(step); + if ( clicked ) { continue; } + safe.uboLog(logPrefix, `Timed out waiting on ${step}`); + break; } - terminate(); }; runAtHtmlElementFn(process); @@ -2001,16 +1816,16 @@ function trustedReplaceOutboundText( propChain = '', rawPattern = '', rawReplacement = '', - ...args + ...varargs ) { if ( propChain === '' ) { return; } const safe = safeSelf(); - const logPrefix = safe.makeLogPrefix('trusted-replace-outbound-text', propChain, rawPattern, rawReplacement, ...args); + const logPrefix = safe.makeLogPrefix('trusted-replace-outbound-text', propChain, rawPattern, rawReplacement, ...varargs); const rePattern = safe.patternToRegex(rawPattern); const replacement = rawReplacement.startsWith('json:') ? safe.JSON_parse(rawReplacement.slice(5)) : rawReplacement; - const extraArgs = safe.getExtraArgs(args); + const extraArgs = safe.parseVarargs(varargs); const reCondition = safe.patternToRegex(extraArgs.condition || ''); proxyApplyFn(propChain, function(context) { const encodedTextBefore = context.reflect(); @@ -2110,7 +1925,7 @@ function trustedSuppressNativeMethod( } } if ( signatureArg.type === 'pattern' ) { - if ( safe.RegExp_test.call(signatureArg.re, targetArg) === false ) { + if ( safe.RegExp_test(signatureArg.re, targetArg) === false ) { return context.reflect(); } } @@ -2252,12 +2067,13 @@ builtinScriptlets.push({ function trustedOverrideElementMethod( methodPath = '', selector = '', - disposition = '' + disposition = '', + ...varargs ) { if ( methodPath === '' ) { return; } const safe = safeSelf(); const logPrefix = safe.makeLogPrefix('trusted-override-element-method', methodPath, selector, disposition); - const extraArgs = safe.getExtraArgs(Array.from(arguments), 3); + const extraArgs = safe.parseVarargs(varargs); proxyApplyFn(methodPath, function(context) { let override = selector === ''; if ( override === false ) { diff --git a/src/js/resources/set-constant.js b/src/js/resources/set-constant.js index 9ee985914d5f7..ced3adf0507d1 100644 --- a/src/js/resources/set-constant.js +++ b/src/js/resources/set-constant.js @@ -89,12 +89,13 @@ registerScriptlet(validateConstantFn, { export function setConstantFn( trusted = false, chain = '', - rawValue = '' + rawValue = '', + ...varargs ) { if ( chain === '' ) { return; } const safe = safeSelf(); const logPrefix = safe.makeLogPrefix('set-constant', chain, rawValue); - const extraArgs = safe.getExtraArgs(Array.from(arguments), 3); + const extraArgs = safe.parseVarargs(varargs); function setConstant(chain, rawValue) { const trappedProp = (( ) => { const pos = chain.lastIndexOf('.'); diff --git a/src/js/resources/stack-trace.js b/src/js/resources/stack-trace.js index c2e535847ee32..7d742135c01a0 100644 --- a/src/js/resources/stack-trace.js +++ b/src/js/resources/stack-trace.js @@ -82,12 +82,13 @@ registerScriptlet(matchesStackTraceFn, { function abortOnStackTrace( chain = '', - needle = '' + needle = '', + ...varargs ) { if ( typeof chain !== 'string' ) { return; } const safe = safeSelf(); const needleDetails = safe.initPattern(needle, { canNegate: true }); - const extraArgs = safe.getExtraArgs(Array.from(arguments), 2); + const extraArgs = safe.parseVarargs(varargs); if ( needle === '' ) { extraArgs.log = 'all'; } const makeProxy = function(owner, chain) { const pos = chain.indexOf('.'); diff --git a/src/js/resources/utils.js b/src/js/resources/utils.js index 52e7a9b450b24..34458578ba0af 100644 --- a/src/js/resources/utils.js +++ b/src/js/resources/utils.js @@ -62,6 +62,87 @@ registerScriptlet(getExceptionTokenFn, { /******************************************************************************/ +export function trapPropertyFn(propChain, handler, options = {}) { + if ( propChain === '' ) { return; } + let owner = self; + let prop = propChain; + for (;;) { + const pos = prop.indexOf('.'); + if ( pos === -1 ) { break; } + owner = owner[prop.slice(0, pos)]; + if ( owner instanceof Object === false ) { return; } + prop = prop.slice(pos + 1); + } + const safe = safeSelf(); + if ( trapPropertyFn.db === undefined ) { + trapPropertyFn.db = new WeakMap(); + trapPropertyFn.entryFromContext = (owner, prop) => { + const handlers = trapPropertyFn.db.get(owner); + return handlers?.get(prop); + }; + trapPropertyFn.getter = (owner, prop) => { + const entry = trapPropertyFn.entryFromContext(owner, prop); + if ( entry === undefined ) { return; } + let r = entry.value; + for ( const desc of entry.stack ) { + try { r = desc.get(); } catch (e) { + if ( entry.canThrow ) { throw e; } + } + } + return r; + }; + trapPropertyFn.setter = (owner, prop, value) => { + const entry = trapPropertyFn.entryFromContext(owner, prop); + if ( entry === undefined ) { return; } + entry.value = value; + for ( const desc of entry.stack ) { + try { desc.set(value); } catch (e) { + if ( entry.canThrow ) { throw e; } + } + } + }; + } + const { db } = trapPropertyFn; + const handlers = db.get(owner) || new Map(); + if ( handlers.size === 0 ) { + db.set(owner, handlers); + } + const entry = handlers.get(prop) || { + value: owner[prop], + stack: [], + }; + entry.stack.push(handler); + if ( entry.stack.length > 1 ) { return entry.value; } + Object.assign(entry, options); + handlers.set(prop, entry); + const desc = safe.Object_getOwnPropertyDescriptor(owner, prop); + if ( desc instanceof safe.Object ) { + if ( desc.get || desc.set ) { + entry.stack.push(desc); + } + } + try { + safe.Object_defineProperty(owner, prop, { + get() { + return trapPropertyFn.getter(owner, prop); + }, + set(value) { + trapPropertyFn.setter(owner, prop, value); + } + }); + } catch { + } + return entry.value; +} +registerScriptlet(trapPropertyFn, { + name: 'trap-property-access.fn', + dependencies: [ + safeSelf, + ], +}); + +/******************************************************************************/ + export function collateFetchArgumentsFn(resource, options) { const safe = safeSelf(); const props = [ @@ -241,3 +322,142 @@ registerScriptlet(generateContentFn, { }); /******************************************************************************/ + +export function onIdleFn(fn, options) { + if ( self.requestIdleCallback ) { + return self.requestIdleCallback(fn, options); + } + return self.requestAnimationFrame(fn); +} +registerScriptlet(onIdleFn, { + name: 'on-idle.fn', +}); + +export function offIdleFn(id) { + if ( self.requestIdleCallback ) { + return self.cancelIdleCallback(id); + } + return self.cancelAnimationFrame(id); +} +registerScriptlet(offIdleFn, { + name: 'off-idle.fn', +}); + +/******************************************************************************/ + +export function sleepFn(ms = 0) { + const nap = ( ) => { + return new Promise(resolve => { + self.requestAnimationFrame(resolve); + }); + } + const until = Date.now() + ms; + const sleep = async resolve => { + do { + await nap(); + } while ( Date.now() < until ); + resolve(); + }; + return new Promise(resolve => { sleep(resolve); }); +} +registerScriptlet(sleepFn, { + name: 'sleep.fn', +}); + +/******************************************************************************/ + +export function lookupElementsFn(directive, until = 0) { + if ( lookupElementsFn.querySelectorEx === undefined ) { + lookupElementsFn.getShadowRoot = elem => { + if ( elem.openOrClosedShadowRoot ) { // Firefox + return elem.openOrClosedShadowRoot; + } + if ( self.chrome?.dom?.openOrClosedShadowRoot ) { // Chromium + return self.chrome.dom.openOrClosedShadowRoot(elem); + } + return elem.shadowRoot; + }; + lookupElementsFn.queryOrEvaluateSelector = (selector, context) => { + if ( selector.startsWith('xpath:') === false ) { + return Array.from(context.querySelectorAll(selector)); + } + const result = document.evaluate(selector.slice(6), context, null, 7, null); + const out = []; + if ( result.resultType === 7 ) { + for ( let i = 0; i < result.snapshotLength; i++ ) { + out[i] = result.snapshotItem(i); + } + } + return out; + } + lookupElementsFn.querySelectorEx = (selector, context = document) => { + const pos = selector.indexOf(' >>> '); + if ( pos === -1 ) { + return lookupElementsFn.queryOrEvaluateSelector(selector, context); + } + const outside = selector.slice(0, pos).trim(); + const inside = selector.slice(pos + 5).trim(); + const elems = lookupElementsFn.queryOrEvaluateSelector(outside, context); + const out = []; + for ( let i = 0; i < elems.length; i++ ) { + const shadowRoot = lookupElementsFn.getShadowRoot(elems[i]); + if ( Boolean(shadowRoot) === false ) { continue; } + lookupElementsFn.querySelectorEx(inside, shadowRoot).forEach(a => out.push(a)); + } + return out; + }; + lookupElementsFn.lookup = directive => { + const beVisible = directive.startsWith('when-visible:'); + const selector = beVisible ? directive.slice(13) : directive; + const elems = lookupElementsFn.querySelectorEx(selector); + if ( beVisible !== true ) { return elems; } + return elems.filter(a => a.checkVisibility({ + opacityProperty: true, + visibilityProperty: true, + })); + }; + lookupElementsFn.lookupAsync = details => { + const elems = lookupElementsFn.lookup(details.directive); + if ( elems.length || Date.now() >= details.until ) { + if ( details.observer ) { + details.observer.disconnect(); + details.observer = undefined; + } + if ( details.timer ) { + offIdleFn(details.timer); + details.timer = undefined; + } + return details.resolve(elems); + } + if ( details.observer === undefined ) { + details.observer = new MutationObserver(( ) => { + lookupElementsFn.lookupAsync(details); + }); + details.observer.observe(document, { + attributes: true, + childList: true, + subtree: true, + }); + } + if ( details.timer === undefined ) { + details.timer = onIdleFn(( ) => { + details.timer = undefined; + lookupElementsFn.lookupAsync(details); + }, { timeout: 151 }); + } + }; + } + if ( until === 0 ) { + return lookupElementsFn.lookup(directive); + } + return new Promise(resolve => { + lookupElementsFn.lookupAsync({ directive, until, resolve }); + }); +} +registerScriptlet(lookupElementsFn, { + name: 'lookup-elements.fn', + dependencies: [ + offIdleFn, + onIdleFn, + ], +}); diff --git a/src/js/resources/vod.js b/src/js/resources/vod.js new file mode 100644 index 0000000000000..f74d259579ce8 --- /dev/null +++ b/src/js/resources/vod.js @@ -0,0 +1,175 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2026-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock + +*/ + +import { modifyXhrResponseFn } from './prevent-xhr.js'; +import { registerScriptlet } from './base.js'; +import { safeSelf } from './safe-self.js'; + +export function mpegdashPrune( + selector = '', + propsToMatch = '' +) { + if ( typeof selector !== 'string' ) { return; } + if ( selector === '' ) { return; } + const safe = safeSelf(); + const logPrefix = safe.makeLogPrefix('mpegdash-prune', selector, propsToMatch); + const queryAll = (xmlDoc, selector) => { + if ( selector.startsWith('xpath:') === false ) { + return Array.from(xmlDoc.querySelectorAll(selector)); + } + const xpr = xmlDoc.evaluate( + selector.slice(6), + xmlDoc, + null, + XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, + null + ); + const out = []; + for ( let i = 0; i < xpr.snapshotLength; i++ ) { + const node = xpr.snapshotItem(i); + out.push(node); + } + return out; + }; + const rePTparse = /^PT(\d+D)?(\d+H)?(\d+M)?([\d.]+S)?$/; + const secondsPerDay = 24 * 60 * 60; + const secondsPerHour = 60 * 60; + const secondsPerMinute = 60; + const secondsFromPT = pt => { + const match = rePTparse.exec(pt); + if ( match === null ) { return; } + let seconds = 0; + if ( match[1] ) { + const d = parseFloat(match[1].slice(0, -1)); + if ( isNaN(d) ) { return; } + seconds += d * secondsPerDay; + } + if ( match[2] ) { + const h = parseFloat(match[2].slice(0, -1)); + if ( isNaN(h) ) { return; } + seconds += h * secondsPerHour; + } + if ( match[3] ) { + const m = parseFloat(match[3].slice(0, -1)); + if ( isNaN(m) ) { return; } + seconds += m * secondsPerMinute; + } + if ( match[4] ) { + const s = parseFloat(match[4].slice(0, -1)); + if ( isNaN(s) ) { return; } + seconds += s; + } + return seconds; + }; + const ptFromSeconds = seconds => { + const parts = [ 'PT' ]; + const d = Math.floor(seconds / secondsPerDay); + if ( d ) { + parts.push(`${d}D`); + seconds -= d * secondsPerDay; + } + const h = Math.floor(seconds / secondsPerHour); + if ( h ) { + parts.push(`${h}H`); + seconds -= h * secondsPerHour; + } + const m = Math.floor(seconds / secondsPerMinute); + if ( m ) { + parts.push(`${m}M`); + seconds -= m * secondsPerMinute; + } + parts.push(`${seconds}S`); + return parts.join(''); + }; + const fixTimeAttributes = xmlDoc => { + try { + const periods = queryAll(xmlDoc, 'MPD > Period'); + if ( periods.length === 0 ) { return; } + let seconds = 0; + for ( const period of periods ) { + const startAttrBefore = period.getAttribute('start'); + const durAttr = period.getAttribute('duration'); + if ( startAttrBefore === null || durAttr === null ) { continue; } + const startAttrAfter = ptFromSeconds(seconds); + period.setAttribute('start', startAttrAfter); + if ( period.hasAttribute('id') ) { + const idAttr = period.getAttribute('id'); + period.setAttribute('id', idAttr.replace(startAttrBefore, startAttrAfter)); + } + seconds += secondsFromPT(durAttr); + } + const mpds = queryAll(xmlDoc, 'MPD[mediaPresentationDuration]'); + if ( mpds.length !== 1 ) { return; } + mpds[0].setAttribute('mediaPresentationDuration', ptFromSeconds(seconds)); + } catch { + } + }; + const pruneFromDoc = xmlDoc => { + try { + if ( selector === '' ) { + const serializer = new XMLSerializer(); + safe.uboLog(logPrefix, `Document is\n\t${serializer.serializeToString(xmlDoc)}`); + } + const items = queryAll(xmlDoc, selector); + if ( items.length === 0 ) { return xmlDoc; } + safe.uboLog(logPrefix, `Patching ${items.length} items`); + for ( const item of items ) { + if ( item.nodeType !== 1 ) { continue; } + item.setAttribute('duration', 'PT0S'); + } + fixTimeAttributes(xmlDoc); + } catch(ex) { + safe.uboErr(logPrefix, `Error: ${ex}`); + } + return xmlDoc; + }; + const pruneFromText = text => { + if ( (/^\s*\s*$/.test(text)) === false ) { + return text; + } + try { + const xmlParser = new DOMParser(); + const xmlDoc = xmlParser.parseFromString(text, 'text/xml'); + pruneFromDoc(xmlDoc); + const serializer = new XMLSerializer(); + text = serializer.serializeToString(xmlDoc); + } catch { + } + return text; + }; + modifyXhrResponseFn(propsToMatch, (xhr, before) => { + if ( before instanceof XMLDocument ) { + return pruneFromDoc(before); + } + if ( typeof before === 'string' ) { + return pruneFromText(before); + } + return before; + }); +} +registerScriptlet(mpegdashPrune, { + name: 'mpegdash-prune.js', + dependencies: [ + modifyXhrResponseFn, + safeSelf, + ], +}); diff --git a/src/js/scriptlet-filtering-core.js b/src/js/scriptlet-filtering-core.js index 5c56423c2b1ff..d6960c863ee9b 100644 --- a/src/js/scriptlet-filtering-core.js +++ b/src/js/scriptlet-filtering-core.js @@ -25,26 +25,13 @@ import { redirectEngine as reng } from './redirect-engine.js'; /******************************************************************************/ -// For debugging convenience: all the top function calls will appear -// at the bottom of a generated content script -const codeSorter = (a, b) => { - if ( a.startsWith('try') ) { return 1; } - if ( b.startsWith('try') ) { return -1; } - return 0; -}; - -const normalizeRawFilter = (parser, sourceIsTrusted = false) => { +const normalizeRawFilter = parser => { const args = parser.getScriptletArgs(); if ( args.length !== 0 ) { let token = `${args[0]}.js`; if ( reng.aliases.has(token) ) { token = reng.aliases.get(token); } - if ( parser.isException() !== true ) { - if ( sourceIsTrusted !== true ) { - if ( reng.tokenRequiresTrust(token) ) { return; } - } - } args[0] = token.slice(0, -3); } return JSON.stringify(args); @@ -61,7 +48,7 @@ const lookupScriptlet = (rawToken, mainMap, isolatedMap, debug = false) => { const fname = match && match[1]; const content = patchScriptlet(fname, details.js, args.slice(1)); if ( fname ) { - targetWorldMap.set(token, details.js); + targetWorldMap.set(token, { code: details.js }); } const dependencies = details.dependencies || []; while ( dependencies.length !== 0 ) { @@ -70,17 +57,20 @@ const lookupScriptlet = (rawToken, mainMap, isolatedMap, debug = false) => { const details = reng.contentFromName(token, 'fn/javascript') || reng.contentFromName(token, 'text/javascript'); if ( details === undefined ) { continue; } - targetWorldMap.set(token, details.js); + targetWorldMap.set(token, { code: details.js }); if ( Array.isArray(details.dependencies) === false ) { continue; } dependencies.push(...details.dependencies); } - targetWorldMap.set(rawToken, [ - 'try {', - `\t${content}`, - '} catch (e) {', - debug ? '\tconsole.error(e);' : '', - '}', - ].join('\n')); + targetWorldMap.set(rawToken, { + code: [ + 'try {', + `\t${content}`, + '} catch (e) {', + debug ? '\tconsole.error(e);' : '', + '}', + ].join('\n'), + priority: details.priority ?? 0, + }); }; // Fill-in scriptlet argument placeholders. @@ -144,7 +134,7 @@ export class ScriptletFilteringEngine { // Only exception filters are allowed to be global. const isException = parser.isException(); - const normalized = normalizeRawFilter(parser, writer.properties.get('trustedSource')); + const normalized = normalizeRawFilter(parser); // Can fail if there is a mismatch with trust requirement if ( normalized === undefined ) { return; } @@ -165,7 +155,8 @@ export class ScriptletFilteringEngine { for ( const { hn, not, bad } of parser.getExtFilterDomainIterator() ) { if ( bad ) { continue; } - const prefix = ((isException ? 1 : 0) ^ (not ? 1 : 0)) ? '-' : '+'; + if ( isException && not ) { continue; } + const prefix = isException || not ? '-' : '+'; writer.push([ 32, hn, `${prefix}${normalized}` ]); } } @@ -251,17 +242,25 @@ export class ScriptletFilteringEngine { } } + // Remember: class statements are not hoisted + const sortedCalls = map => Array.from(map).sort((a, b) => { + const an = a[1].code, bn = b[1].code; + const ap = a[1].priority, bp = b[1].priority; + if ( ap === bp ) { return an.localeCompare(bn); } + if ( ap === undefined ) { return -1; } + if ( bp === undefined ) { return 1; } + return bp - ap; + }).map(a => a[1].code); + const mainWorldCode = []; - for ( const js of mainWorldMap.values() ) { + for ( const js of sortedCalls(mainWorldMap) ) { mainWorldCode.push(js); } - mainWorldCode.sort(codeSorter); const isolatedWorldCode = []; - for ( const js of isolatedWorldMap.values() ) { + for ( const js of sortedCalls(isolatedWorldMap) ) { isolatedWorldCode.push(js); } - isolatedWorldCode.sort(codeSorter); const scriptletDetails = { mainWorld: mainWorldCode.join('\n\n'), diff --git a/src/js/static-dnr-filtering.js b/src/js/static-dnr-filtering.js index 4356dd61caa9f..0183f49707b72 100644 --- a/src/js/static-dnr-filtering.js +++ b/src/js/static-dnr-filtering.js @@ -27,6 +27,7 @@ import { } from './static-filtering-io.js'; import { LineIterator } from './text-utils.js'; +import { getTrustedTokens } from './trusted-tokens.js'; import staticNetFilteringEngine from './static-net-filtering.js'; /******************************************************************************/ @@ -107,28 +108,25 @@ function addExtendedToDNR(context, parser) { context.scriptletFilters = new Map(); } const exception = parser.isException(); - const args = parser.getScriptletArgs(); + const args = parser.getScriptletArgs() || []; const argsToken = JSON.stringify(args); for ( const { hn, not, bad } of parser.getExtFilterDomainIterator() ) { if ( bad ) { continue; } - if ( exception ) { continue; } - let details = context.scriptletFilters.get(argsToken); - if ( details === undefined ) { - context.scriptletFilters.set(argsToken, details = { args }); + if ( exception && not ) { continue; } + const details = context.scriptletFilters.get(argsToken) ?? {}; + if ( details.args === undefined ) { + context.scriptletFilters.set(argsToken, details); + details.args = args; if ( context.trustedSource ) { details.trustedSource = true; } } - if ( not ) { - if ( details.excludeMatches === undefined ) { - details.excludeMatches = []; - } + if ( exception || not ) { + details.excludeMatches ??= []; details.excludeMatches.push(hn); continue; } - if ( details.matches === undefined ) { - details.matches = []; - } + details.matches ??= []; if ( details.matches.includes('*') ) { continue; } if ( hn === '*' ) { details.matches = [ '*' ]; @@ -227,7 +225,9 @@ function addExtendedToDNR(context, parser) { if ( not && exception ) { continue; } if ( not || exception ) { excludeMatches.push(hn); - } else if ( hn !== '*' ) { + } else if ( hn === '*' ) { + addGenericCosmeticFilter(context, compiled, false); + } else { matches.push(hn); } } @@ -276,6 +276,7 @@ function addToDNR(context, list) { nativeCssHas: env.includes('native_css_has'), badTypes: [ sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE ], trustedSource: list.trustedSource || undefined, + trustedTokens: getTrustedTokens(), }); const compiler = staticNetFilteringEngine.createCompiler(); @@ -435,25 +436,6 @@ function finalizeRuleset(context, network) { rulesetMap.set(ruleId++, rule); } } - mergeRules(rulesetMap, 'resourceTypes'); - mergeRules(rulesetMap, 'removeParams'); - mergeRules(rulesetMap, 'initiatorDomains'); - mergeRules(rulesetMap, 'requestDomains'); - mergeRules(rulesetMap, 'responseHeaders'); - - // Convert back single-entry requestDomains into pattern-based filters - // https://github.com/uBlockOrigin/uBOL-home/issues/327 - // TODO: Remove when (if) Safari is changed to interpret requestDomains as - // in other browsers. - for ( const rule of rulesetMap.values() ) { - const { condition } = rule; - if ( condition?.requestDomains === undefined ) { continue; } - if ( condition.requestDomains.length !== 1 ) { continue; } - if ( condition.urlFilter !== undefined ) { continue; } - if ( condition.regexFilter !== undefined ) { continue; } - condition.urlFilter = `||${condition.requestDomains[0]}^`; - condition.requestDomains = undefined; - } // Patch id const rulesetFinal = []; diff --git a/src/js/static-filtering-parser.js b/src/js/static-filtering-parser.js index 6dbc07aa94277..90a3c564fff96 100644 --- a/src/js/static-filtering-parser.js +++ b/src/js/static-filtering-parser.js @@ -100,6 +100,7 @@ export const AST_ERROR_OPTION_BADVALUE = 1 << iota++; export const AST_ERROR_OPTION_EXCLUDED = 1 << iota++; export const AST_ERROR_IF_TOKEN_UNKNOWN = 1 << iota++; export const AST_ERROR_UNTRUSTED_SOURCE = 1 << iota++; +export const AST_ERROR_CAPABILITY = 1 << iota++; iota = 0; const NODE_RIGHT_INDEX = iota++; @@ -584,6 +585,7 @@ const astTemplates = { type: NODE_TYPE_EXT_PATTERN_COSMETIC, beg: 0, end: 0, + register: true, }], }], }], @@ -603,6 +605,7 @@ export const preparserIfTokens = new Set([ 'ext_ublock', 'ext_ubol', 'ext_devbuild', + 'env_brave', 'env_chromium', 'env_edge', 'env_firefox', @@ -1454,12 +1457,29 @@ export class AstFilterParser { case NODE_TYPE_NET_OPTION_NAME_REDIRECT: case NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE: { realBad = abstractTypeCount || behaviorTypeCount || unredirectableTypeCount; + if ( realBad ) { break; } + if ( isException || isBadfilter ) { break; } + const { trustedSource, trustedTokens } = this.options; + if ( trustedSource ) { break; } + if ( trustedTokens instanceof Set === false ) { break; } + const value = this.getNetOptionValue(modifierType); + let { token } = parseRedirectValue(value); + if ( trustedTokens.has(token) ) { + this.astError = AST_ERROR_UNTRUSTED_SOURCE; + realBad = true; + } break; } case NODE_TYPE_NET_OPTION_NAME_REPLACE: { realBad = abstractTypeCount || behaviorTypeCount || unredirectableTypeCount; if ( realBad ) { break; } if ( isException || isBadfilter ) { break; } + if ( this.options.canFilterResponseBody !== true ) { + this.addFlags(AST_FLAG_HAS_ERROR); + this.astError = AST_ERROR_CAPABILITY; + realBad = true; + break; + } if ( this.options.trustedSource !== true ) { this.astError = AST_ERROR_UNTRUSTED_SOURCE; realBad = true; @@ -1519,18 +1539,20 @@ export class AstFilterParser { indexOfNetAnchor(s) { const end = s.length; - if ( end === 0 ) { return end; } + if ( end === 0 ) { return 0; } let j = s.lastIndexOf('$'); if ( j === -1 ) { return end; } - if ( (j+1) === end ) { return end; } + let htmlFilteringRule = false; for (;;) { - const before = s.charAt(j-1); - if ( before === '$' ) { return -1; } + if ( s.charCodeAt(j-1) === 0x24 /* $ */ ) { + htmlFilteringRule = true; + } if ( this.reNetOptionTokens.test(s.slice(j+1)) ) { return j; } if ( j === 0 ) { break; } j = s.lastIndexOf('$', j-1); if ( j === -1 ) { break; } } + if ( htmlFilteringRule ) { return -1; } return end; } @@ -2185,7 +2207,11 @@ export class AstFilterParser { if ( c0 === 0x2F /* / */ ) { this.domainRegexValueParser.nextArg(this.raw, beg+1); end = this.domainRegexValueParser.separatorEnd; - isRegex = true; + if ( end <= parentEnd ) { + isRegex = true; + } else { + end = -1; + } } else if ( c0 === 0x5B /* [ */ && this.startsWith('[$domain=/', beg) ) { end = this.indexOf('/]', beg + 10, parentEnd); if ( end !== -1 ) { end += 2; } @@ -2338,12 +2364,12 @@ export class AstFilterParser { break; } case NODE_TYPE_EXT_PATTERN_SCRIPTLET_TOKEN: { - if ( this.interactive !== true ) { break; } if ( isException ) { break; } - const { trustedSource, trustedScriptletTokens } = this.options; - if ( trustedScriptletTokens instanceof Set === false ) { break; } + const { trustedSource, trustedTokens } = this.options; + if ( trustedSource ) { break; } + if ( trustedTokens instanceof Set === false ) { break; } const token = this.getNodeString(targetNode); - if ( trustedScriptletTokens.has(token) && trustedSource !== true ) { + if ( trustedTokens.has(token) ) { this.astError = AST_ERROR_UNTRUSTED_SOURCE; realBad = true; } @@ -2386,6 +2412,10 @@ export class AstFilterParser { return this.parseExtPatternResponseheader(parent); } this.astTypeFlavor = AST_TYPE_EXTENDED_HTML; + if ( this.options.canFilterResponseBody !== true ) { + this.astError = AST_ERROR_CAPABILITY; + return 0; + } return this.parseExtPatternHtml(parent); } // ##... @@ -3309,6 +3339,7 @@ export class ExtSelectorCompiler { ':style', ]); this.proceduralOperatorNames = new Set([ + 'content', 'has-text', 'if', 'if-not', @@ -3956,6 +3987,8 @@ export class ExtSelectorCompiler { const arg = this.astSerialize(parts, false); if ( arg === undefined ) { return; } switch ( operator ) { + case 'content': + return this.compileSelector(arg); case 'has-text': return this.compileText(arg); case 'if': @@ -4191,6 +4224,7 @@ export const proceduralOperatorTokens = new Map([ [ '-abp-contains', 0b00 ], [ '-abp-has', 0b00, ], [ 'contains', 0b00, ], + [ 'content', 0b01, ], [ 'has', 0b01 ], [ 'has-text', 0b01 ], [ 'if', 0b00 ], @@ -4204,9 +4238,10 @@ export const proceduralOperatorTokens = new Map([ [ 'not', 0b01 ], [ 'nth-ancestor', 0b00 ], [ 'others', 0b11 ], - [ 'remove', 0b11 ], + [ 'remove', 0b01 ], [ 'remove-attr', 0b11 ], [ 'remove-class', 0b11 ], + [ 'shadow', 0b11, ], [ 'style', 0b11 ], [ 'upward', 0b01 ], [ 'watch-attr', 0b11 ], @@ -4222,6 +4257,7 @@ export const utils = (( ) => { [ 'ext_ublock', 'ublock' ], [ 'ext_ubol', 'ubol' ], [ 'ext_devbuild', 'devbuild' ], + [ 'env_brave', 'brave' ], [ 'env_chromium', 'chromium' ], [ 'env_edge', 'edge' ], [ 'env_firefox', 'firefox' ], @@ -4230,7 +4266,6 @@ export const utils = (( ) => { [ 'env_mv3', 'mv3' ], [ 'env_safari', 'safari' ], [ 'cap_html_filtering', 'html_filtering' ], - [ 'cap_user_stylesheet', 'user_stylesheet' ], [ 'cap_ipaddress', 'ipaddress' ], [ 'false', 'false' ], // Hoping ABP-only list maintainers can at least make use of it to @@ -4373,13 +4408,10 @@ export const utils = (( ) => { } if ( part instanceof Object === false ) { continue; } const content = part.content; + if ( typeof content !== 'string' ) { continue; } const slices = this.splitter(content, env); - for ( let i = 0, n = slices.length - 1; i < n; i++ ) { + for ( let i = 0, n = slices.length; i < n; i += 2 ) { const slice = content.slice(slices[i+0], slices[i+1]); - if ( (i & 1) !== 0 ) { - out.push(slice); - continue; - } let lastIndex = 0; for (;;) { const match = reInclude.exec(slice); @@ -4407,7 +4439,7 @@ export const utils = (( ) => { static prune(content, env) { const parts = this.splitter(content, env); const out = []; - for ( let i = 0, n = parts.length - 1; i < n; i += 2 ) { + for ( let i = 0, n = parts.length; i < n; i += 2 ) { const beg = parts[i+0]; const end = parts[i+1]; out.push(content.slice(beg, end)); diff --git a/src/js/static-net-filtering.js b/src/js/static-net-filtering.js index 189c7c2baefaa..c23909602e6e3 100644 --- a/src/js/static-net-filtering.js +++ b/src/js/static-net-filtering.js @@ -19,6 +19,8 @@ Home: https://github.com/gorhill/uBlock */ +import '../lib/regexanalyzer/regex.js'; + import * as sfp from './static-filtering-parser.js'; import { dropTask, queueTask } from './tasks.js'; @@ -1436,19 +1438,24 @@ class FilterNotType { static dnrFromCompiled(args, rule) { rule.condition = rule.condition || {}; const rc = rule.condition; - if ( rc.excludedResourceTypes === undefined ) { - rc.excludedResourceTypes = [ 'main_frame' ]; - } + rc.excludedResourceTypes ??= []; let bits = args[1]; for ( let i = 1; bits !== 0 && i < typeValueToDNRTypeName.length; i++ ) { const bit = 1 << (i - 1); if ( (bits & bit) === 0 ) { continue; } bits &= ~bit; const type = typeValueToDNRTypeName[i]; - if ( type === undefined ) { continue; } + if ( Boolean(type) === false ) { continue; } if ( rc.excludedResourceTypes.includes(type) ) { continue; } rc.excludedResourceTypes.push(type); } + if ( rc.excludedResourceTypes.length ) { + if ( rc.resourceTypes?.includes('main_frame') ) { + rc.resourceTypes = rc.resourceTypes.filter(a => a !== 'main_frame'); + } else { + rc.excludedResourceTypes.push('main_frame'); + } + } } static keyFromArgs(args) { @@ -3100,7 +3107,7 @@ class FilterOnHeaders { const { bad, name, not, value } = refs.$parsed; if ( bad ) { return false; } const headerValue = $httpHeaders.lookup(name); - if ( headerValue === undefined ) { return false; } + if ( headerValue === undefined ) { return not; } if ( value === '' ) { return true; } let { re } = refs.$parsed; if ( re === undefined ) { diff --git a/src/js/storage.js b/src/js/storage.js index 66a3352394ab2..8de3e58f4cc1a 100644 --- a/src/js/storage.js +++ b/src/js/storage.js @@ -35,6 +35,7 @@ import { import { ubolog, ubologSet } from './console.js'; import cosmeticFilteringEngine from './cosmetic-filtering.js'; +import { getTrustedTokens } from './trusted-tokens.js'; import { hostnameFromURI } from './uri-utils.js'; import io from './assets.js'; import logger from './logger.js'; @@ -960,7 +961,6 @@ onBroadcast(msg => { if ( vAPI.Net.canSuspend() ) { vAPI.net.suspend(); } - redirectEngine.reset(); staticExtFilteringEngine.reset(); staticNetFilteringEngine.reset(); µb.selfieManager.destroy(); @@ -1107,16 +1107,16 @@ onBroadcast(msg => { // Populate the writer with information potentially useful to the // client compilers. - const trustedSource = details.trustedSource === true; if ( details.assetKey ) { writer.properties.set('name', details.assetKey); - writer.properties.set('trustedSource', trustedSource); } const assetName = details.assetKey ? details.assetKey : '?'; const parser = new sfp.AstFilterParser({ - trustedSource, + trustedSource: details.trustedSource === true, maxTokenLength: staticNetFilteringEngine.MAX_TOKEN_LENGTH, nativeCssHas: vAPI.webextFlavor.env.includes('native_css_has'), + canFilterResponseBody: µb.canFilterResponseData, + trustedTokens: getTrustedTokens(), }); const compiler = staticNetFilteringEngine.createCompiler(parser); const lineIter = new LineIterator( diff --git a/src/js/text-encode.js b/src/js/text-encode.js index b1e850b29c7f6..b6870e0c40df6 100644 --- a/src/js/text-encode.js +++ b/src/js/text-encode.js @@ -37,6 +37,7 @@ const textEncode = (( ) => { [ 'windows-1250', 'windows-1250' ], [ 'cp1250', 'windows-1250' ], [ 'x-cp1250', 'windows-1250' ], + [ 'iso-8859-2', 'windows-1250' ], [ 'windows-1251', 'windows-1251' ], [ 'cp1251', 'windows-1251' ], diff --git a/src/js/trusted-tokens.js b/src/js/trusted-tokens.js new file mode 100644 index 0000000000000..0e4b76ff1a800 --- /dev/null +++ b/src/js/trusted-tokens.js @@ -0,0 +1,60 @@ +/******************************************************************************* + + uBlock Origin Lite - a comprehensive, MV3-compliant content blocker + Copyright (C) 2026-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock +*/ + +import { builtinScriptlets } from './resources/scriptlets.js'; +import redirectResources from './redirect-resources.js'; + +/******************************************************************************/ + +const addTrustedToken = (out, ...tokens) => { + for ( const token of tokens ) { + out.add(token); + if ( token.endsWith('.js') === false ) { continue; } + out.add(token.slice(0, -3)); + } +}; + +let trustedTokens; + +/******************************************************************************/ + +export function getTrustedTokens() { + if ( trustedTokens ) { return trustedTokens; } + const out = new Set(); + for ( const { name, requiresTrust, aliases } of builtinScriptlets ) { + if ( requiresTrust !== true ) { continue; } + addTrustedToken(out, name); + if ( Array.isArray(aliases) === false ) { continue; } + addTrustedToken(out, ...aliases); + } + for ( const [ name, { requiresTrust, alias } ] of redirectResources ) { + if ( requiresTrust !== true ) { continue; } + addTrustedToken(out, name); + if ( alias === undefined ) { continue; } + if ( typeof alias === 'string' ) { + addTrustedToken(out, alias); + } else if ( Array.isArray(alias) ) { + addTrustedToken(out, ...alias); + } + } + trustedTokens = out; + return out; +} diff --git a/src/lib/regexanalyzer/CHANGES.md b/src/lib/regexanalyzer/CHANGES.md index 3c4eb8bd7bacf..fb36b0a81ca8a 100644 --- a/src/lib/regexanalyzer/CHANGES.md +++ b/src/lib/regexanalyzer/CHANGES.md @@ -13,3 +13,7 @@ Imported version 1.2.0 of the library from https://github.com/foo123/RegexAnalyzer/blob/1.2.0/src/js/Regex.js Minimally modified the code to make it ECMAscript `export`-/`import`-friendly. + +2026-05-13 + +Expose `Regex` object as a property of `globalThis`. diff --git a/src/lib/regexanalyzer/regex.js b/src/lib/regexanalyzer/regex.js index 35a27169769de..b90f849970aef 100644 --- a/src/lib/regexanalyzer/regex.js +++ b/src/lib/regexanalyzer/regex.js @@ -2271,6 +2271,10 @@ var Regex = { Analyzer : Analyzer, Composer : Composer }; +/* Add as global value */ +if ( globalThis ) { + globalThis.Regex = Regex; +} /* export the module */ return Regex; })(); diff --git a/src/web_accessible_resources/google-ima-dai.js b/src/web_accessible_resources/google-ima-dai.js new file mode 100644 index 0000000000000..365bc8fc66d19 --- /dev/null +++ b/src/web_accessible_resources/google-ima-dai.js @@ -0,0 +1,630 @@ +// Repo: https://github.com/AdguardTeam/Scriptlets +// Source: https://github.com/AdguardTeam/Scriptlets/blob/master/src/redirects/google-ima3-dai.ts +// License: https://github.com/AdguardTeam/Scriptlets/blob/master/LICENSE (GPLv3) +// Commit: https://github.com/AdguardTeam/Scriptlets/blob/eedd995c41/src/redirects/google-ima3-dai.ts +/* eslint-disable */ +(function(source, args) { + const flag = "done"; + const uniqueIdentifier = source.uniqueId + source.name + "_" + (Array.isArray(args) ? args.join("_") : ""); + if (source.uniqueId) { + if (Window.prototype.toString[uniqueIdentifier] === flag) { + return; + } + } + function GoogleIma3Dai(source) { + var streamEventTypes = { + AD_BREAK_ENDED: "adBreakEnded", + AD_BREAK_STARTED: "adBreakStarted", + AD_PERIOD_ENDED: "adPeriodEnded", + AD_PERIOD_STARTED: "adPeriodStarted", + AD_PROGRESS: "adProgress", + CLICK: "click", + COMPLETE: "complete", + CUEPOINTS_CHANGED: "cuepointsChanged", + ERROR: "error", + FIRST_QUARTILE: "firstquartile", + HIDE_AD_UI: "hideAdUi", + LOADED: "loaded", + MIDPOINT: "midpoint", + PAUSED: "paused", + RESUMED: "resumed", + SHOW_AD_UI: "showAdUi", + SKIPPABLE_STATE_CHANGED: "skippableStateChanged", + SKIPPED: "skip", + STARTED: "started", + STREAM_INITIALIZED: "streamInitialized", + THIRD_QUARTILE: "thirdquartile", + VIDEO_CLICKED: "videoClicked" + }; + var isRecord = function isRecord(value) { + return typeof value === "object" && value !== null; + }; + var schedule = function schedule(callback) { + if (typeof requestAnimationFrame === "function") { + requestAnimationFrame(callback); + return; + } + setTimeout(callback, 0); + }; + var toStringRecord = function toStringRecord(value) { + if (!isRecord(value)) { + return {}; + } + var result = {}; + var propertyNames = Object.keys(value); + for (var propertyIndex = 0; propertyIndex < propertyNames.length; propertyIndex += 1) { + var propertyName = propertyNames[propertyIndex]; + result[propertyName] = String(value[propertyName]); + } + return result; + }; + var getStringValue = function getStringValue(value) { + return typeof value === "string" && value.length > 0 ? value : null; + }; + var initializeEventHandler = function initializeEventHandler(instance) { + instance.listeners = new Map; + }; + var normalizeEventTypes = function normalizeEventTypes(type) { + if (typeof type === "string") { + return [ type ]; + } + if (!Array.isArray(type)) { + return []; + } + var eventTypes = []; + for (var eventTypeIndex = 0; eventTypeIndex < type.length; eventTypeIndex += 1) { + var eventType = type[eventTypeIndex]; + if (typeof eventType === "string") { + eventTypes.push(eventType); + } + } + return eventTypes; + }; + var initializeStreamRequest = function initializeStreamRequest(instance, streamRequest) { + instance.adTagParameters = {}; + instance.apiKey = null; + instance.authToken = null; + instance.format = "hls"; + instance.networkCode = null; + instance.omidAccessModeRules = null; + instance.streamActivityMonitorId = null; + if (isRecord(streamRequest)) { + Object.assign(instance, streamRequest); + } + instance.adTagParameters = toStringRecord(instance.adTagParameters); + if (typeof instance.format !== "string" || instance.format.length === 0) { + instance.format = "hls"; + } + }; + var initializePodStreamRequest = function initializePodStreamRequest(instance, podStreamRequest) { + initializeStreamRequest(instance, podStreamRequest); + instance.customAssetKey = typeof instance.customAssetKey === "string" ? instance.customAssetKey : ""; + }; + var EventHandler = function EventHandler() { + initializeEventHandler(this); + }; + EventHandler.prototype.addEventListener = function(type, listener) { + if (typeof listener !== "function") { + return; + } + var eventTypes = normalizeEventTypes(type); + for (var eventTypeIndex = 0; eventTypeIndex < eventTypes.length; eventTypeIndex += 1) { + var eventType = eventTypes[eventTypeIndex]; + if (!this.listeners.has(eventType)) { + this.listeners.set(eventType, new Set); + } + var listeners = this.listeners.get(eventType); + if (listeners) { + listeners.add(listener); + } + } + }; + EventHandler.prototype.removeEventListener = function(type, listener) { + if (typeof listener !== "function") { + return; + } + var eventTypes = normalizeEventTypes(type); + for (var eventTypeIndex = 0; eventTypeIndex < eventTypes.length; eventTypeIndex += 1) { + var listeners = this.listeners.get(eventTypes[eventTypeIndex]); + if (!listeners) { + continue; + } + listeners.delete(listener); + } + }; + EventHandler.prototype.dispatchEvent = function(streamEvent) { + var listeners = this.listeners.get(streamEvent.type); + if (!listeners) { + return; + } + for (var _i = 0, _Array$from = Array.from(listeners); _i < _Array$from.length; _i++) { + var _listener = _Array$from[_i]; + try { + _listener(streamEvent); + } catch (error) { + logMessage(source, error); + } + } + }; + var StreamRequest = function StreamRequest(streamRequest) { + initializeStreamRequest(this, streamRequest); + }; + var LiveStreamRequest = function LiveStreamRequest(liveStreamRequest) { + initializeStreamRequest(this, liveStreamRequest); + this.assetKey = typeof this.assetKey === "string" ? this.assetKey : ""; + }; + Object.setPrototypeOf(LiveStreamRequest.prototype, StreamRequest.prototype); + var PodStreamRequest = function PodStreamRequest(podStreamRequest) { + initializePodStreamRequest(this, podStreamRequest); + }; + Object.setPrototypeOf(PodStreamRequest.prototype, StreamRequest.prototype); + var VideoStitcherLiveStreamRequest = function VideoStitcherLiveStreamRequest(videoStitcherLiveStreamRequest) { + initializePodStreamRequest(this, videoStitcherLiveStreamRequest); + this.liveStreamEventId = typeof this.liveStreamEventId === "string" ? this.liveStreamEventId : ""; + this.oAuthToken = typeof this.oAuthToken === "string" ? this.oAuthToken : null; + this.projectNumber = typeof this.projectNumber === "string" ? this.projectNumber : null; + this.region = typeof this.region === "string" ? this.region : null; + this.videoStitcherSessionOptions = isRecord(this.videoStitcherSessionOptions) ? this.videoStitcherSessionOptions : null; + }; + Object.setPrototypeOf(VideoStitcherLiveStreamRequest.prototype, PodStreamRequest.prototype); + var VideoStitcherVodStreamRequest = function VideoStitcherVodStreamRequest(videoStitcherVodStreamRequest) { + initializeStreamRequest(this, videoStitcherVodStreamRequest); + this.adTagUrl = typeof this.adTagUrl === "string" ? this.adTagUrl : ""; + this.contentSourceUrl = typeof this.contentSourceUrl === "string" ? this.contentSourceUrl : ""; + this.oAuthToken = typeof this.oAuthToken === "string" ? this.oAuthToken : null; + this.projectNumber = typeof this.projectNumber === "string" ? this.projectNumber : null; + this.region = typeof this.region === "string" ? this.region : null; + this.videoStitcherSessionOptions = isRecord(this.videoStitcherSessionOptions) ? this.videoStitcherSessionOptions : null; + this.vodConfigId = typeof this.vodConfigId === "string" ? this.vodConfigId : ""; + }; + Object.setPrototypeOf(VideoStitcherVodStreamRequest.prototype, StreamRequest.prototype); + var VODStreamRequest = function VODStreamRequest(vodStreamRequest) { + initializeStreamRequest(this, vodStreamRequest); + this.contentSourceId = typeof this.contentSourceId === "string" ? this.contentSourceId : ""; + this.videoId = typeof this.videoId === "string" ? this.videoId : ""; + }; + Object.setPrototypeOf(VODStreamRequest.prototype, StreamRequest.prototype); + var StreamData = function StreamData(streamData) { + this.adPeriodData = null; + this.adProgressData = null; + this.cuepoints = []; + this.errorMessage = null; + this.manifestFormat = "HLS"; + this.streamId = null; + this.subtitles = []; + this.url = ""; + if (isRecord(streamData)) { + Object.assign(this, streamData); + } + }; + var StreamEvent = function StreamEvent(type, streamData, ad) { + this.type = type; + this.streamData = streamData || new StreamData; + this.ad = ad || null; + }; + StreamEvent.Type = streamEventTypes; + StreamEvent.prototype.getAd = function() { + return this.ad; + }; + StreamEvent.prototype.getStreamData = function() { + return this.streamData; + }; + var UiSettings = function UiSettings() { + this.locale = ""; + }; + UiSettings.prototype.getLocale = function() { + return this.locale; + }; + UiSettings.prototype.setLocale = function(locale) { + this.locale = locale; + }; + var daiSdkFeatureFlagsStorage = new WeakMap; + var getStoredDaiSdkFeatureFlags = function getStoredDaiSdkFeatureFlags(instance) { + var storedFeatureFlags = daiSdkFeatureFlagsStorage.get(instance); + if (storedFeatureFlags) { + return storedFeatureFlags; + } + var nextFeatureFlags = {}; + daiSdkFeatureFlagsStorage.set(instance, nextFeatureFlags); + return nextFeatureFlags; + }; + var DaiSdkSettingsContainer = function DaiSdkSettingsContainer() { + daiSdkFeatureFlagsStorage.set(this, {}); + }; + DaiSdkSettingsContainer.prototype.getFeatureFlags = function() { + return getStoredDaiSdkFeatureFlags(this); + }; + DaiSdkSettingsContainer.prototype.setFeatureFlags = function(featureFlags) { + daiSdkFeatureFlagsStorage.set(this, Object.assign({}, featureFlags)); + }; + var normalizeStreamRequest = function normalizeStreamRequest(streamRequest) { + if (streamRequest instanceof StreamRequest) { + return streamRequest; + } + if (isRecord(streamRequest)) { + if (typeof streamRequest.liveStreamEventId === "string") { + return new VideoStitcherLiveStreamRequest(streamRequest); + } + if (typeof streamRequest.contentSourceUrl === "string" || typeof streamRequest.vodConfigId === "string" || typeof streamRequest.adTagUrl === "string") { + return new VideoStitcherVodStreamRequest(streamRequest); + } + if (typeof streamRequest.customAssetKey === "string") { + return new PodStreamRequest(streamRequest); + } + if (typeof streamRequest.assetKey === "string") { + return new LiveStreamRequest(streamRequest); + } + if (typeof streamRequest.contentSourceId === "string" || typeof streamRequest.videoId === "string") { + return new VODStreamRequest(streamRequest); + } + } + return new StreamRequest; + }; + var hasLiveIdentifiers = function hasLiveIdentifiers(streamRequest) { + var liveStreamRequest = streamRequest; + return typeof liveStreamRequest.assetKey === "string" && liveStreamRequest.assetKey.length > 0; + }; + var hasVideoStitcherLiveIdentifiers = function hasVideoStitcherLiveIdentifiers(streamRequest) { + var videoStitcherLiveStreamRequest = streamRequest; + return typeof videoStitcherLiveStreamRequest.liveStreamEventId === "string" && videoStitcherLiveStreamRequest.liveStreamEventId.length > 0; + }; + var hasPodIdentifiers = function hasPodIdentifiers(streamRequest) { + var podStreamRequest = streamRequest; + return typeof podStreamRequest.networkCode === "string" && podStreamRequest.networkCode.length > 0 && typeof podStreamRequest.customAssetKey === "string" && podStreamRequest.customAssetKey.length > 0; + }; + var hasVideoStitcherVodIdentifiers = function hasVideoStitcherVodIdentifiers(streamRequest) { + var videoStitcherVodStreamRequest = streamRequest; + var hasContentSourceUrl = typeof videoStitcherVodStreamRequest.contentSourceUrl === "string" && videoStitcherVodStreamRequest.contentSourceUrl.length > 0; + var hasVodConfigId = typeof videoStitcherVodStreamRequest.vodConfigId === "string" && videoStitcherVodStreamRequest.vodConfigId.length > 0; + return hasContentSourceUrl || hasVodConfigId; + }; + var hasVodIdentifiers = function hasVodIdentifiers(streamRequest) { + var vodStreamRequest = streamRequest; + return typeof vodStreamRequest.contentSourceId === "string" && vodStreamRequest.contentSourceId.length > 0 && typeof vodStreamRequest.videoId === "string" && vodStreamRequest.videoId.length > 0; + }; + var hasIdentifiers = function hasIdentifiers(streamRequest) { + return hasLiveIdentifiers(streamRequest) || hasPodIdentifiers(streamRequest) || hasVideoStitcherLiveIdentifiers(streamRequest) || hasVideoStitcherVodIdentifiers(streamRequest) || hasVodIdentifiers(streamRequest); + }; + var getFallbackStreamId = function getFallbackStreamId(streamRequest) { + var liveStreamRequest = streamRequest; + var videoStitcherLiveStreamRequest = streamRequest; + var videoStitcherVodStreamRequest = streamRequest; + var vodStreamRequest = streamRequest; + if (typeof videoStitcherVodStreamRequest.vodConfigId === "string" && videoStitcherVodStreamRequest.vodConfigId.length > 0) { + return `mock-video-stitcher-vod-${videoStitcherVodStreamRequest.vodConfigId}`; + } + if (typeof videoStitcherVodStreamRequest.contentSourceUrl === "string" && videoStitcherVodStreamRequest.contentSourceUrl.length > 0) { + return "mock-video-stitcher-vod"; + } + if (typeof videoStitcherLiveStreamRequest.liveStreamEventId === "string" && videoStitcherLiveStreamRequest.liveStreamEventId.length > 0) { + return `mock-video-stitcher-live-${videoStitcherLiveStreamRequest.liveStreamEventId}`; + } + if (typeof liveStreamRequest.assetKey === "string" && liveStreamRequest.assetKey.length > 0) { + return `mock-live-${liveStreamRequest.assetKey}`; + } + if (typeof vodStreamRequest.videoId === "string" && vodStreamRequest.videoId.length > 0) { + return `mock-vod-${vodStreamRequest.videoId}`; + } + return "mock-stream"; + }; + var getDefaultManifestFormat = function getDefaultManifestFormat(streamRequest) { + return typeof streamRequest.format === "string" && streamRequest.format.toLowerCase() === "dash" ? "DASH" : "HLS"; + }; + var createStreamData = function createStreamData(streamRequest, cuepoints, errorMessage, streamDataOverrides) { + var streamData = new StreamData({ + cuepoints: cuepoints.slice(), + errorMessage: errorMessage, + manifestFormat: getDefaultManifestFormat(streamRequest), + streamId: getFallbackStreamId(streamRequest), + url: "" + }); + if (isRecord(streamDataOverrides)) { + Object.assign(streamData, streamDataOverrides); + } + return streamData; + }; + var appendRequestParameters = function appendRequestParameters(requestUrl, streamRequest) { + var parameterNames = Object.keys(streamRequest.adTagParameters); + for (var parameterIndex = 0; parameterIndex < parameterNames.length; parameterIndex += 1) { + var parameterName = parameterNames[parameterIndex]; + requestUrl.searchParams.set(parameterName, streamRequest.adTagParameters[parameterName]); + } + if (streamRequest.apiKey) { + requestUrl.searchParams.set("api-key", streamRequest.apiKey); + } + if (streamRequest.authToken) { + requestUrl.searchParams.set("auth-token", streamRequest.authToken); + } + if (streamRequest.streamActivityMonitorId) { + requestUrl.searchParams.set("dai-sam-id", streamRequest.streamActivityMonitorId); + } + }; + var buildLiveRequestUrl = function buildLiveRequestUrl(streamRequest, hostName) { + var requestUrl = new URL(`${hostName}/ssai/event/${streamRequest.assetKey}/streams`); + appendRequestParameters(requestUrl, streamRequest); + return requestUrl.toString(); + }; + var buildPodRequestUrl = function buildPodRequestUrl(streamRequest, hostName) { + var requestUrl = new URL(`${hostName}/ssai/pods/api/v1/network/${streamRequest.networkCode}` + `/custom_asset/${streamRequest.customAssetKey}/stream`); + var manifestType = streamRequest.format.toLowerCase() === "dash" ? "dash" : "hls"; + appendRequestParameters(requestUrl, streamRequest); + requestUrl.searchParams.set("manifest-type", manifestType); + return requestUrl.toString(); + }; + var buildVodRequestUrl = function buildVodRequestUrl(streamRequest, hostName) { + var requestFormat = streamRequest.format.toLowerCase() === "dash" ? "dash" : "hls"; + var requestUrl = new URL(`${hostName}/ondemand/${requestFormat}/content/${streamRequest.contentSourceId}` + `/vid/${streamRequest.videoId}/streams`); + appendRequestParameters(requestUrl, streamRequest); + return requestUrl.toString(); + }; + var MAIN_HOST_NAME = "https://dai.google.com"; + var FALLBACK_HOST_NAME = "https://pubads.g.doubleclick.net"; + var getStreamRequestUrls = function getStreamRequestUrls(streamRequest) { + if (hasPodIdentifiers(streamRequest)) { + return [ buildPodRequestUrl(streamRequest, MAIN_HOST_NAME), buildPodRequestUrl(streamRequest, FALLBACK_HOST_NAME) ]; + } + if (hasLiveIdentifiers(streamRequest)) { + return [ buildLiveRequestUrl(streamRequest, MAIN_HOST_NAME), buildLiveRequestUrl(streamRequest, FALLBACK_HOST_NAME) ]; + } + if (hasVodIdentifiers(streamRequest)) { + return [ buildVodRequestUrl(streamRequest, MAIN_HOST_NAME), buildVodRequestUrl(streamRequest, FALLBACK_HOST_NAME) ]; + } + return []; + }; + var readFetchResponseData = async function readFetchResponseData(response) { + var typedResponse = response; + if (typedResponse && typedResponse.ok === false) { + throw new Error(`Stream initialization failed with status ${String(typedResponse.status || 0)}`); + } + if (typedResponse && typeof typedResponse.json === "function") { + var jsonResponse = await typedResponse.json(); + return isRecord(jsonResponse) ? jsonResponse : {}; + } + return isRecord(response) ? response : {}; + }; + var getResponseErrorMessage = function getResponseErrorMessage(responseData) { + return getStringValue(responseData.errorMessage) || getStringValue(responseData.error_message); + }; + var createStreamDataFromResponse = function createStreamDataFromResponse(streamRequest, cuepoints, responseData) { + var podManifestUrl = getStringValue(responseData.pod_manifest_url) || getStringValue(responseData.podManifestUrl) || ""; + var responseStreamId = getStringValue(responseData.stream_id) || getStringValue(responseData.streamId); + var streamUrl = getStringValue(responseData.stream_manifest) || getStringValue(responseData.streamUrl) || podManifestUrl || ""; + var responseErrorMessage = getResponseErrorMessage(responseData); + var hasInitializedStream = streamUrl.length > 0 || responseStreamId !== null && responseStreamId.length > 0; + var errorMessage = responseErrorMessage || (hasInitializedStream ? null : "Stream initialization response missing stream URL"); + var manifestFormat = getStringValue(responseData.manifest_format) || getStringValue(responseData.manifestFormat) || getDefaultManifestFormat(streamRequest); + var streamId = responseStreamId || getFallbackStreamId(streamRequest); + var subtitles = Array.isArray(responseData.subtitles) ? responseData.subtitles : []; + return createStreamData(streamRequest, cuepoints, errorMessage, { + manifestFormat: manifestFormat, + podManifestUrl: podManifestUrl, + pod_manifest_url: podManifestUrl, + streamId: streamId, + subtitles: subtitles, + url: streamUrl + }); + }; + var getErrorMessage = function getErrorMessage(error) { + if (isRecord(error) && typeof error.message === "string" && error.message.length > 0) { + return error.message; + } + return "Stream initialization failed"; + }; + var hideAdUiElement = function hideAdUiElement(streamManager) { + if (!streamManager.adUiElement) { + return; + } + streamManager.adUiElement.style.display = "none"; + }; + var showVideoControls = function showVideoControls(streamManager) { + if (!streamManager.videoElement || streamManager.videoElement.controls) { + return; + } + streamManager.videoElement.controls = true; + }; + var handleContentLoaded = function handleContentLoaded(streamManager) { + hideAdUiElement(streamManager); + showVideoControls(streamManager); + }; + var isContentLoadedEventType = function isContentLoadedEventType(eventType) { + return eventType === StreamEvent.Type.LOADED || eventType === StreamEvent.Type.STREAM_INITIALIZED; + }; + var StreamManager = function StreamManager(videoElement, adUiElement, uiSettings) { + initializeEventHandler(this); + this.videoElement = videoElement || null; + this.adUiElement = adUiElement || null; + this.uiSettings = uiSettings || new UiSettings; + this.clickElement = adUiElement || null; + this.streamData = new StreamData; + this.streamMonitor = {}; + this.streamRequest = null; + this.cuepoints = []; + this.lastMetadata = null; + this.lastTimedMetadata = null; + }; + Object.setPrototypeOf(StreamManager.prototype, EventHandler.prototype); + StreamManager.prototype.contentTimeForStreamTime = function(streamTime) { + return typeof streamTime === "number" ? streamTime : 0; + }; + StreamManager.prototype.destroy = function() { + this.reset(); + }; + StreamManager.prototype.focus = function() { + var clickElement = this.clickElement; + if (!clickElement || typeof clickElement.focus !== "function") { + return; + } + try { + clickElement.focus(); + } catch (error) { + logMessage(source, error); + } + }; + StreamManager.prototype.getAdSkippableState = function() { + return true; + }; + StreamManager.prototype.getStreamData = function() { + return this.streamData; + }; + StreamManager.prototype.loadStreamMetadata = function() { + handleContentLoaded(this); + this.dispatchEvent(new StreamEvent(StreamEvent.Type.LOADED, this.streamData)); + }; + StreamManager.prototype.onTimedMetadata = function(metadata) { + this.lastTimedMetadata = metadata; + }; + StreamManager.prototype.previousCuePointForStreamTime = function(streamTime) { + var previousCuePoint = null; + for (var cuepointIndex = 0; cuepointIndex < this.cuepoints.length; cuepointIndex += 1) { + var cuepoint = this.cuepoints[cuepointIndex]; + if (typeof cuepoint.start !== "number") { + continue; + } + if (cuepoint.start <= streamTime) { + previousCuePoint = cuepoint; + } + } + return previousCuePoint; + }; + StreamManager.prototype.processMetadata = function(type, data, timestamp) { + this.lastMetadata = { + data: data, + timestamp: timestamp, + type: type + }; + }; + StreamManager.prototype.replaceAdTagParameters = function(adTagParameters) { + if (!this.streamRequest) { + this.streamRequest = new StreamRequest; + } + this.streamRequest.adTagParameters = toStringRecord(adTagParameters); + }; + StreamManager.prototype.requestStream = function(streamRequest) { + var _this = this; + var normalizedRequest = normalizeStreamRequest(streamRequest); + this.streamRequest = normalizedRequest; + var dispatchStreamEvent = function dispatchStreamEvent(eventType, streamData) { + _this.streamData = streamData; + if (isContentLoadedEventType(eventType)) { + handleContentLoaded(_this); + } + schedule((function() { + _this.dispatchEvent(new StreamEvent(StreamEvent.Type.STREAM_INITIALIZED, streamData)); + _this.dispatchEvent(new StreamEvent(eventType, streamData)); + })); + }; + if (!hasIdentifiers(normalizedRequest)) { + dispatchStreamEvent(StreamEvent.Type.ERROR, createStreamData(normalizedRequest, this.cuepoints, "Missing stream request identifiers")); + return; + } + var requestUrls = getStreamRequestUrls(normalizedRequest); + if (requestUrls.length > 0) { + var activeRequest = normalizedRequest; + var _fetchStreamData = async function fetchStreamData(requestIndex) { + try { + var fetchResponse = await fetch(requestUrls[requestIndex], { + method: "POST", + credentials: "include" + }); + var responseData = await readFetchResponseData(fetchResponse); + if (_this.streamRequest !== activeRequest) { + return; + } + var _streamData = createStreamDataFromResponse(activeRequest, _this.cuepoints, responseData); + var eventType = _streamData.errorMessage ? StreamEvent.Type.ERROR : StreamEvent.Type.LOADED; + dispatchStreamEvent(eventType, _streamData); + } catch (error) { + if (_this.streamRequest !== activeRequest) { + return; + } + if (requestIndex + 1 < requestUrls.length) { + await _fetchStreamData(requestIndex + 1); + return; + } + dispatchStreamEvent(StreamEvent.Type.ERROR, createStreamData(activeRequest, _this.cuepoints, getErrorMessage(error))); + } + }; + _fetchStreamData(0); + return; + } + dispatchStreamEvent(StreamEvent.Type.LOADED, createStreamData(normalizedRequest, this.cuepoints, null)); + }; + StreamManager.prototype.reset = function() { + this.cuepoints = []; + this.lastMetadata = null; + this.lastTimedMetadata = null; + this.streamData = new StreamData; + this.streamRequest = null; + }; + StreamManager.prototype.setClickElement = function(clickElement) { + if (this.adUiElement) { + return; + } + this.clickElement = clickElement; + }; + StreamManager.prototype.streamTimeForContentTime = function(contentTime) { + return typeof contentTime === "number" ? contentTime : 0; + }; + var api = { + DaiSdkSettings: new DaiSdkSettingsContainer, + LiveStreamRequest: LiveStreamRequest, + PodStreamRequest: PodStreamRequest, + StreamData: StreamData, + StreamEvent: StreamEvent, + StreamManager: StreamManager, + StreamRequest: StreamRequest, + UiSettings: UiSettings, + VideoStitcherLiveStreamRequest: VideoStitcherLiveStreamRequest, + VideoStitcherVodStreamRequest: VideoStitcherVodStreamRequest, + VODStreamRequest: VODStreamRequest + }; + var globalWindow = window; + var googleNamespace = isRecord(globalWindow.google) ? globalWindow.google : {}; + if (!isRecord(globalWindow.google)) { + globalWindow.google = googleNamespace; + } + var imaNamespace = isRecord(googleNamespace.ima) ? googleNamespace.ima : {}; + googleNamespace.ima = imaNamespace; + var daiNamespace = isRecord(imaNamespace.dai) ? imaNamespace.dai : {}; + imaNamespace.dai = daiNamespace; + var apiNamespace = isRecord(daiNamespace.api) ? daiNamespace.api : {}; + daiNamespace.api = apiNamespace; + Object.assign(apiNamespace, api); + hit(source); + } + function hit(e) { + if (e.verbose) { + try { + var n = console.trace.bind(console), i = "[AdGuard] "; + "corelibs" === e.engine ? i += e.ruleText : (e.domainName && (i += `${e.domainName}`), + e.args ? i += `#%#//scriptlet('${e.name}', '${e.args.join("', '")}')` : i += `#%#//scriptlet('${e.name}')`), + n && n(i); + } catch (e) {} + "function" == typeof window.__debug && window.__debug(e); + } + } + function logMessage(e, o) { + var r = arguments.length > 2 && void 0 !== arguments[2] && arguments[2], a = !(arguments.length > 3 && void 0 !== arguments[3]) || arguments[3], {name: n, verbose: g} = e; + if (r || g) { + var i = console.log; + a ? i(`${n}: ${o}`) : Array.isArray(o) ? i(`${n}:`, ...o) : i(`${n}:`, o); + } + } + const updatedArgs = args ? [].concat(source).concat(args) : [ source ]; + try { + GoogleIma3Dai.apply(this, updatedArgs); + if (source.uniqueId) { + Object.defineProperty(Window.prototype.toString, uniqueIdentifier, { + value: flag, + enumerable: false, + writable: false, + configurable: false + }); + } + } catch (e) { + console.log(e); + } +})({ + name: "google-ima3-dai", + args: [] +}, []); diff --git a/src/web_accessible_resources/google-ima.js b/src/web_accessible_resources/google-ima.js index a3f6126628524..8359aa9593877 100644 --- a/src/web_accessible_resources/google-ima.js +++ b/src/web_accessible_resources/google-ima.js @@ -24,7 +24,9 @@ * - https://github.com/uBlockOrigin/uAssets/issues/31018 * **/ - + +/* eslint-disable indent */ + 'use strict'; /* This Source Code Form is subject to the terms of the Mozilla Public @@ -41,7 +43,7 @@ */ if (!window.google || !window.google.ima || !window.google.ima.VERSION) { - const VERSION = "3.517.2"; + const VERSION = "3.764.0"; const ima = {}; class AdDisplayContainer { @@ -481,7 +483,8 @@ if (!window.google || !window.google.ima || !window.google.ima.VERSION) { return true; } } - } catch (_) {} + } catch { + } return false; }; diff --git a/src/web_accessible_resources/googlesyndication_adsbygoogle.js b/src/web_accessible_resources/googlesyndication_adsbygoogle.js index 294d054e51a23..49ebcc64706d9 100644 --- a/src/web_accessible_resources/googlesyndication_adsbygoogle.js +++ b/src/web_accessible_resources/googlesyndication_adsbygoogle.js @@ -20,37 +20,54 @@ */ (function() { - 'use strict'; - const init = ( ) => { - window.adsbygoogle = { - loaded: true, - push: function() { - } - }; - const phs = document.querySelectorAll('.adsbygoogle'); - const css = 'height:1px!important;max-height:1px!important;max-width:1px!important;width:1px!important;'; - for ( let i = 0; i < phs.length; i++ ) { - const id = `aswift_${i}`; - if ( document.querySelector(`iframe#${id}`) !== null ) { continue; } - const fr = document.createElement('iframe'); - fr.id = id; - fr.style = css; - const cfr = document.createElement('iframe'); - cfr.id = `google_ads_frame${i}`; - fr.appendChild(cfr); - const ph = phs[i]; - ph.appendChild(fr); - ph.setAttribute('data-adsbygoogle-status', 'done'); + self.adsbygoogle = self.adsbygoogle || { + loaded: true, + push: function() { + ; } }; - if ( - document.querySelectorAll('.adsbygoogle').length === 0 && - document.readyState === 'loading' - ) { - window.addEventListener('DOMContentLoaded', init, { once: true }); - } else { - init(); - } + let adCount = 1; + const setupAd = (placeholder) => { + const fr = document.createElement('iframe'); + fr.id = `aswift_${adCount}`; + fr.setAttribute('name', fr.id); + adCount += 1; + placeholder.dataset.adsbygoogleStatus = 'loading'; + placeholder.dataset.adStatus = 'loading'; + placeholder.appendChild(fr); + fr.addEventListener('load', ( ) => { + placeholder.dataset.adsbygoogleStatus = 'done'; + placeholder.dataset.adStatus = 'filled'; + fr.dataset.loadComplete = 'true'; + }, { once: true }); + fr.contentWindow.location = 'data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+DQo8aHRtbD4NCiAgICA8aGVhZD48dGl0bGU+PC90aXRsZT48L2hlYWQ+DQogICAgPGJvZHk+PC9ib2R5Pg0KPC9odG1sPg=='; + }; + const process = ( ) => { + const phs = document.querySelectorAll('.adsbygoogle:not([data-ad-status][data-adsbygoogle-status])'); + for ( const ph of phs ) { + setupAd(ph); + } + }; + process(); + + let observer = new MutationObserver(( ) => { + if ( process.timer !== undefined ) { return; } + process.timer = self.requestAnimationFrame(( ) => { + process.timer = undefined; + process(); + },); + }); + observer.observe(document, { + attributes: true, + attributeFilter: [ 'class' ], + childList: true, + subtree: true, + }); + + setTimeout(( ) => { + observer.disconnect(); + observer = undefined; + }, 20000); })(); /* diff --git a/src/web_accessible_resources/piano-analytics.js b/src/web_accessible_resources/piano-analytics.js new file mode 100644 index 0000000000000..12732e77ac17d --- /dev/null +++ b/src/web_accessible_resources/piano-analytics.js @@ -0,0 +1,6 @@ +self.pa = { + getVisitorId() { + }, + sendEvent() { + }, +}; diff --git a/tools/jsonpath-tests.html b/tools/jsonpath-tests.html new file mode 100644 index 0000000000000..5d01aababe1a4 --- /dev/null +++ b/tools/jsonpath-tests.html @@ -0,0 +1,48 @@ + + + + + +JSONPath: rfc9535 conformance + + + +

JSONPath: rfc9535 conformance

+
+
+ + + + + + + diff --git a/tools/jsonpath-tests.js b/tools/jsonpath-tests.js new file mode 100644 index 0000000000000..d0c47cce38a90 --- /dev/null +++ b/tools/jsonpath-tests.js @@ -0,0 +1,408 @@ +import { JSONPath } from '../src/js/jsonpath.js'; + +const jsonpathTests = [ { + // https://www.rfc-editor.org/rfc/rfc9535.html#section-2.3.1.3 + json: `{ + "o": {"j j": {"k.k": 3}}, + "'": {"@": 2} + }`, + queries: [ + { q: `$.o['j j']`, r: [ + ['o','j j'], + ] }, + { q: `$.o['j j']['k.k']`, r: [ + ['o','j j','k.k'], + ] }, + { q: `$.o["j j"]["k.k"]`, r: [ + ['o','j j','k.k'], + ] }, + { q: `$["'"]["@"]`, r: [ + ["'",'@'], + ] }, + ], +},{ + // https://www.rfc-editor.org/rfc/rfc9535.html#section-2.3.2.3 + json: `{ + "o": {"j": 1, "k": 2}, + "a": [5, 3] + }`, + queries: [ + { q: `$[*]`, r: [ + ['o'], + ['a'], + ] }, + { q: `$.o[*]`, r: [ + ['o','j'], + ['o','k'], + ] }, + { q: `$.o[*, *]`, r: [ + ['o','j'], + ['o','k'], + ['o','j'], + ['o','k'], + ] }, + { q: `$.a[*]`, r: [ + ['a',0], + ['a',1], + ] }, + ], +},{ + // https://www.rfc-editor.org/rfc/rfc9535.html#section-2.3.3.3 + json: `["a","b"]`, + queries: [ + { q: `$[1]`, r: [ + [1], + ] }, + { q: `$[-2]`, r: [ + [0], + ] }, + ], +},{ + // https://www.rfc-editor.org/rfc/rfc9535.html#section-2.3.4.3 + json: `["a", "b", "c", "d", "e", "f", "g"]`, + queries: [ + { q: `$[1:3]`, r: [ + [1], + [2], + ] }, + { q: `$[5:]`, r: [ + [5], + [6], + ] }, + { q: `$[1:5:2]`, r: [ + [1], + [3], + ] }, + { q: `$[5:1:-2]`, r: [ + [5], + [3], + ] }, + { q: `$[::-1]`, r: [ + [6], + [5], + [4], + [3], + [2], + [1], + [0], + ] }, + ], +},{ + // https://www.rfc-editor.org/rfc/rfc9535.html#section-2.3.5.3-7 + json: `{ + "a": [3, 5, 1, 2, 4, 6, + {"b": "j"}, + {"b": "k"}, + {"b": {}}, + {"b": "kilo"} + ], + "o": {"p": 1, "q": 2, "r": 3, "s": 5, "t": {"u": 6}}, + "e": "f" + }`, + queries: [ + { q: `$.a[?@.b == 'kilo']`, r: [ + ['a', 9], + ] }, + { q: `$.a[?(@.b == 'kilo')]`, r: [ + ['a', 9], + ] }, + { q: `$.a[?@>3.5]`, r: [ + ['a', 1], + ['a', 4], + ['a', 5], + ] }, + { q: `$.a[?@.b]`, r: [ + ['a', 6], + ['a', 7], + ['a', 8], + ['a', 9], + ] }, + { q: `$[?@.*]`, r: [ + ['a'], + ['o'], + ] }, + { q: `$[?@[?@.b]]`, r: [ + ['a'], + ] }, + { q: `$.o[?@<3, ?@<3]`, r: [ + ['o', 'p'], + ['o', 'q'], + ['o', 'q'], + ['o', 'p'], + ] }, + { q: `$.a[?@<2 || @.b == "k"]`, r: [ + ['a', 2], + ['a', 7], + ] }, + { q: `$.a[?match(@.b, "[jk]")]`, r: [ + ['a', 6], + ['a', 7], + ] }, + { q: `$.a[?search(@.b, "[jk]")]`, r: [ + ['a', 6], + ['a', 7], + ['a', 9], + ] }, + { q: `$.o[?@>1 && @<4]`, r: [ + ['o', 'q'], + ['o', 'r'], + ] }, + { q: `$.o[?@.u || @.x]`, r: [ + ['o', 't'], + ] }, + { q: `$.a[?@.b == $.x]`, r: [ + ['a', 0], + ['a', 1], + ['a', 2], + ['a', 3], + ['a', 4], + ['a', 5], + ] }, + { q: `$.a[?@ == @]`, r: [ + ['a', 0], + ['a', 1], + ['a', 2], + ['a', 3], + ['a', 4], + ['a', 5], + ['a', 6], + ['a', 7], + ['a', 8], + ] }, + ], +},{ + // https://www.rfc-editor.org/rfc/rfc9535.html#section-2.5.1.3 + json: `["a", "b", "c", "d", "e", "f", "g"]`, + queries: [ + { q: `$[0, 3]`, r: [ + [0], + [3], + ] }, + { q: `$[0:2, 5]`, r: [ + [0], + [1], + [5], + ] }, + { q: `$[0, 0]`, r: [ + [0], + [0], + ] }, + ], +},{ + // https://www.rfc-editor.org/rfc/rfc9535.html#section-2.5.2.3 + json: `{ + "o": {"j": 1, "k": 2}, + "a": [5, 3, [{"j": 4}, {"k": 6}]] + }`, + queries: [ + { q: `$..j`, r: [ + ['o', 'j'], + ['a', 2, 0, 'j'], + ] }, + { q: `$..[0]`, r: [ + ['a', 0], + ['a', 2, 0], + ] }, + { q: `$..*`, r: [ + ['o'], + ['a'], + ['o', 'j'], + ['o', 'k'], + ['a', 0], + ['a', 1], + ['a', 2], + ['a', 2, 0], + ['a', 2, 1], + ['a', 2, 0, 'j'], + ['a', 2, 1, 'k'], + ] }, + { q: `$..o`, r: [ + ['o'], + ] }, + { q: `$.o..[*, *]`, r: [ + ['o', 'j'], + ['o', 'k'], + ['o', 'k'], + ['o', 'j'], + ] }, + { q: `$.a..[0, 1]`, r: [ + ['a', 0], + ['a', 1], + ['a', 2, 0], + ['a', 2, 1], + ] }, + ], +},{ + // https://www.rfc-editor.org/rfc/rfc9535.html#section-2.6.1 + json: `{"a": null, "b": [null], "c": [{}], "null": 1}`, + queries: [ + { q: `$.a`, r: [ + ['a'], + ] }, + { q: `$.a[0]`, r: [ + ] }, + { q: `$.a.d`, r: [ + ] }, + { q: `$.b[0]`, r: [ + ['b', 0], + ] }, + { q: `$.b[*]`, r: [ + ['b', 0], + ] }, + { q: `$.b[?@]`, r: [ + ['b', 0], + ] }, + { q: `$.b[?@==null]`, r: [ + ['b', 0], + ] }, + { q: `$.c[?@.d==null]`, r: [ + ] }, + { q: `$.null`, r: [ + ['null'], + ] }, + ], +},{ + // https://www.rfc-editor.org/rfc/rfc9535.html#section-1.5 + json: `{ "store": { + "book": [ + { "category": "reference", + "author": "Nigel Rees", + "title": "Sayings of the Century", + "price": 8.95 + }, + { "category": "fiction", + "author": "Evelyn Waugh", + "title": "Sword of Honour", + "price": 12.99 + }, + { "category": "fiction", + "author": "Herman Melville", + "title": "Moby Dick", + "isbn": "0-553-21311-3", + "price": 8.99 + }, + { "category": "fiction", + "author": "J. R. R. Tolkien", + "title": "The Lord of the Rings", + "isbn": "0-395-19395-8", + "price": 22.99 + } + ], + "bicycle": { + "color": "red", + "price": 19.95 + } + } + }`, + queries: [ + { q: `$.store.book[*].author`, r: [ + ['store', 'book', 0, 'author'], + ['store', 'book', 1, 'author'], + ['store', 'book', 2, 'author'], + ['store', 'book', 3, 'author'], + ] }, + { q: `$..author`, r: [ + ['store', 'book', 0, 'author'], + ['store', 'book', 1, 'author'], + ['store', 'book', 2, 'author'], + ['store', 'book', 3, 'author'], + ] }, + { q: `$.store.*`, r: [ + ['store', 'book'], + ['store', 'bicycle'], + ] }, + { q: `$.store..price`, r: [ + ['store', 'book', 0, 'price'], + ['store', 'book', 1, 'price'], + ['store', 'book', 2, 'price'], + ['store', 'book', 3, 'price'], + ['store', 'bicycle', 'price'], + ] }, + { q: `$..book[2]`, r: [ + ['store', 'book', 2], + ] }, + { q: `$..book[-1]`, r: [ + ['store', 'book', 3], + ] }, + { q: `$..book[-1:]`, r: [ + ['store', 'book', 3], + ] }, + { q: `$..book[0,1]`, r: [ + ['store', 'book', 0], + ['store', 'book', 1], + ] }, + { q: `$..book[:2]`, r: [ + ['store', 'book', 0], + ['store', 'book', 1], + ] }, + { q: `$..book[?@.isbn]`, r: [ + ['store', 'book', 2], + ['store', 'book', 3], + ] }, + { q: `$..book[?@.price<10]`, r: [ + ['store', 'book', 0], + ['store', 'book', 2], + ] }, + { q: `$..*`, r: [ + ['store'], + ['store', 'book'], + ['store', 'book', 0], + ['store', 'book', 0, 'category'], + ['store', 'book', 0, 'author'], + ['store', 'book', 0, 'title'], + ['store', 'book', 0, 'price'], + ['store', 'book', 1], + ['store', 'book', 1, 'category'], + ['store', 'book', 1, 'author'], + ['store', 'book', 1, 'title'], + ['store', 'book', 1, 'price'], + ['store', 'book', 2], + ['store', 'book', 2, 'category'], + ['store', 'book', 2, 'author'], + ['store', 'book', 2, 'title'], + ['store', 'book', 2, 'isbn'], + ['store', 'book', 2, 'price'], + ['store', 'book', 3], + ['store', 'book', 3, 'category'], + ['store', 'book', 3, 'author'], + ['store', 'book', 3, 'title'], + ['store', 'book', 3, 'isbn'], + ['store', 'book', 3, 'price'], + ['store', 'bicycle'], + ['store', 'bicycle', 'color'], + ['store', 'bicycle', 'price'], + ] }, + ], +} ]; + +const jsonp = new JSONPath(); +const arrayCompare = (a, b) => + JSON.stringify(a).localeCompare(JSON.stringify(b)); +const formatResult = a => { + return a.sort(arrayCompare).map(a => JSON.stringify(a)).join('\n'); +}; + +for ( const tests of jsonpathTests ) { + const obj = JSON.parse(tests.json); + for ( const { q, r } of tests.queries ) { + jsonp.compile(`v2:${q}`); + const actual = formatResult(jsonp.evaluate(obj)?.map(a => a.slice(1))); + const expected = formatResult(r); + console.log(`${q}\n${expected}\n${actual}`); + const fragment = document.querySelector('#test-result').content.cloneNode(true); + const div = fragment.children[0]; + div.children[0].textContent = q; + if ( expected !== '' ) { + div.children[1].textContent = expected; + } + if ( actual !== expected ) { + if ( actual !== '' ) { + div.children[2].textContent = actual; + } + div.children[2].classList.add('fail'); + } else { + div.children[2].textContent = ''; + } + document.querySelector('main').append(fragment); + } +} diff --git a/tools/jsonpath-tool.html b/tools/jsonpath-tool.html index f783db46b693b..e1c55f841ce29 100644 --- a/tools/jsonpath-tool.html +++ b/tools/jsonpath-tool.html @@ -57,7 +57,21 @@ resize: vertical; } #jsonpath-input { + display: flex; + gap: 1em; +} +#jsonpath-input > input { font-size: medium; + flex-grow: 1; +} +#jsonpath-input > button { + font-size: larger; +} +#jsonpath-input > button::after { + content: '\21C8'; +} +section.collapsed + #jsonpath-input > button::after { + content: '\21CA'; } #jsonpath-result { background-color: #eee; @@ -69,9 +83,11 @@

uBO-flavored JSONPath tool

-
-
- +
+
+ + +
 
@@ -84,6 +100,7 @@

uBO-flavored JSONPath tool

// http://localhost:8000/tools/jsonpath-tool.html import { JSONPath } from '../src/js/jsonpath.js'; + //import { JSONPath } from 'https://raw.rawgit.net/gorhill/uBlock/refs/tags/1.71.0/src/js/jsonpath.js'; let aLastText = JSON.stringify({ store: { @@ -146,7 +163,7 @@

uBO-flavored JSONPath tool

} function process() { - const input = document.querySelector('#jsonpath-input'); + const input = document.querySelector('#jsonpath-input > input'); const jsonpath = input.value; jsonp.compile(jsonpath); const jsonDataIn = readJSON(); @@ -156,6 +173,7 @@

uBO-flavored JSONPath tool

const jsonDataOut = readJSON(); const objAfter = jsonp.apply(jsonDataOut); const bText = JSON.stringify(objAfter !== undefined ? objAfter : jsonDataOut, null, 2); + collapse(false); cmMergeView.b.dispatch({ changes: { from: 0, to: cmMergeView.b.state.doc.length, @@ -164,6 +182,19 @@

uBO-flavored JSONPath tool

}); } + function collapse(afterState) { + const section = document.querySelector('main > section'); + const beforeState = section.classList.contains('collapsed'); + afterState ??= !beforeState; + if ( afterState === beforeState ) { return; } + section.classList.toggle('collapsed', afterState); + if ( afterState ) { + cmMergeView.reconfigure({ collapseUnchanged: { } }); + } else { + cmMergeView.reconfigure({ collapseUnchanged: undefined }); + } + } + const jsonp = new JSONPath(); let jsonDataIn = {}; let processTimer; @@ -172,6 +203,18 @@

uBO-flavored JSONPath tool

aDoc: aLastText, aUpdateListener: info => { if ( info.docChanged === false ) { return; } + for ( const transaction of info.transactions ) { + if ( transaction.isUserEvent('input.paste') === false ) { continue; } + const { doc } = info.state; + const before = doc.toString(); + let insert; + try { insert = JSON.stringify(JSON.parse(before), null, 2); } + catch { } + if ( Boolean(insert) === false ) { break; } + collapse(false); + info.view.dispatch({ changes: { from: 0, to: doc.length, insert } }); + return; + } if ( processTimer !== undefined ) { return; } processTimer = setTimeout(( ) => { processTimer = undefined; @@ -184,10 +227,13 @@

uBO-flavored JSONPath tool

}, document.querySelector('section')); { - const input = document.querySelector('#jsonpath-input'); - input.addEventListener('input', ( ) => { - process(); - }); + const input = document.querySelector('#jsonpath-input > input'); + input.addEventListener('input', ( ) => { process(); }); + } + + { + const button = document.querySelector('#jsonpath-input > button'); + button.addEventListener('click', ( ) => { collapse(); }); } process(); diff --git a/tools/make-mv3.sh b/tools/make-mv3.sh index 6a4226737bab7..62925783bbdca 100755 --- a/tools/make-mv3.sh +++ b/tools/make-mv3.sh @@ -56,7 +56,7 @@ UBOL_DIR=$(pwd) cd - > /dev/null mkdir -p "$UBOL_DIR"/css/fonts -mkdir -p "$UBOL_DIR"/js +mkdir -p "$UBOL_DIR"/js/offscreen mkdir -p "$UBOL_DIR"/img mkdir -p "$UBOL_DIR"/lib @@ -87,7 +87,8 @@ cp "$UBO_DIR"/src/js/fa-icons.js "$UBOL_DIR"/js/ cp "$UBO_DIR"/src/js/i18n.js "$UBOL_DIR"/js/ cp "$UBO_DIR"/src/js/jsonpath.js "$UBOL_DIR"/js/ cp "$UBO_DIR"/src/js/redirect-resources.js "$UBOL_DIR"/js/ -cp "$UBO_DIR"/src/js/regex-analyzer.js "$UBOL_DIR"/js/ +cp "$UBO_DIR"/src/js/regex-analyzer.js "$UBOL_DIR"/js/offscreen/ +cp "$UBO_DIR"/src/js/trusted-tokens.js "$UBOL_DIR"/js/ cp -R "$UBO_DIR"/src/js/resources "$UBOL_DIR"/js/ cp "$UBO_DIR"/src/js/static-filtering-parser.js "$UBOL_DIR"/js/ cp "$UBO_DIR"/src/js/urlskip.js "$UBOL_DIR"/js/ @@ -105,6 +106,7 @@ cp platform/mv3/extension/*.json "$UBOL_DIR"/ cp platform/mv3/extension/css/* "$UBOL_DIR"/css/ cp -R platform/mv3/extension/js/* "$UBOL_DIR"/js/ cp platform/mv3/"$PLATFORM"/ext-compat.js "$UBOL_DIR"/js/ 2>/dev/null || : +cp platform/mv3/"$PLATFORM"/ext-offscreen.js "$UBOL_DIR"/js/ 2>/dev/null || : cp platform/mv3/"$PLATFORM"/css-api.js "$UBOL_DIR"/js/scripting/ 2>/dev/null || : cp platform/mv3/"$PLATFORM"/css-user.js "$UBOL_DIR"/js/scripting/ 2>/dev/null || : cp platform/mv3/extension/img/* "$UBOL_DIR"/img/ @@ -124,6 +126,8 @@ cp platform/mv3/extension/lib/codemirror/codemirror-ubol/LICENSE \ "$UBOL_DIR"/lib/codemirror/codemirror-quickstart.LICENSE mkdir -p "$UBOL_DIR"/lib/csstree cp "$UBO_DIR"/src/lib/csstree/* "$UBOL_DIR"/lib/csstree/ +cp platform/mv3/extension/lib/s14e-serializer/s14e-serializer.js \ + "$UBOL_DIR"/lib/ echo "*** uBOLite.mv3: Generating rulesets" UBOL_BUILD_DIR=$(mktemp -d) @@ -132,14 +136,15 @@ mkdir -p "$UBOL_BUILD_DIR" cp platform/mv3/*.json "$UBOL_BUILD_DIR"/ cp platform/mv3/*.js "$UBOL_BUILD_DIR"/ cp platform/mv3/*.mjs "$UBOL_BUILD_DIR"/ +cp platform/mv3/extension/js/ubo-parser.js "$UBOL_BUILD_DIR"/js/ cp platform/mv3/extension/js/utils.js "$UBOL_BUILD_DIR"/js/ -cp platform/mv3/extension/js/make-scriptlets.js "$UBOL_BUILD_DIR"/js/ -cp platform/mv3/extension/js/safe-replace.js "$UBOL_BUILD_DIR"/js/ -cp "$UBO_DIR"/src/js/regex-analyzer.js "$UBOL_BUILD_DIR"/js/ -cp -R "$UBO_DIR"/src/lib/regexanalyzer "$UBOL_BUILD_DIR"/ +cp "$UBO_DIR"/src/lib/punycode.js "$UBOL_BUILD_DIR"/js/ +cp -R "$UBO_DIR"/src/lib/regexanalyzer "$UBOL_BUILD_DIR"/js/ cp -R "$UBO_DIR"/src/js/resources "$UBOL_BUILD_DIR"/js/ +cp "$UBO_DIR"/src/js/trusted-tokens.js "$UBOL_BUILD_DIR"/js/ cp -R platform/mv3/scriptlets "$UBOL_BUILD_DIR"/ -cp platform/mv3/extension/js/scriptlet.template.js "$UBOL_BUILD_DIR"/scriptlets/ +cp -R platform/mv3/extension/js/offscreen "$UBOL_BUILD_DIR"/js/ +cp "$UBO_DIR"/src/js/regex-analyzer.js "$UBOL_BUILD_DIR"/js/offscreen/ mkdir -p "$UBOL_BUILD_DIR"/web_accessible_resources cp "$UBO_DIR"/src/web_accessible_resources/* "$UBOL_BUILD_DIR"/web_accessible_resources/ cp -R platform/mv3/"$PLATFORM" "$UBOL_BUILD_DIR"/